/* ---------------------------------------------------------------------------
   Class 12 revision notes - site styles.
   The reasoning behind every choice here is in docs/10-website.md. Read that
   before changing a token; the values are derived from the brief, not taste.

   Two things are load-bearing and easy to break by accident:
     1. --step is the baseline grid. The ruled paper lines and the body
        line-height are both 28px, which is why text sits ON the rules instead
        of drifting across them. Change one and you must change the other.
     2. The marks-map segment widths are set inline by the builder from real
        marks. Never add a min-width here - a 4-mark unit is meant to look
        like a 4-mark unit.
--------------------------------------------------------------------------- */

:root {
  --ink:       #101620;
  --ink-2:     #161d28;
  --ink-3:     #1b2430;
  --rule:      #1f2733;
  --chalk:     #e8ecf4;
  --chalk-dim: #8b95a8;
  --mark:      #ffb454;
  --accent:    var(--mark);

  --step: 28px;
  --measure: 68ch;

  --display: "Bricolage Grotesque", "Segoe UI", system-ui, sans-serif;
  --body: "IBM Plex Sans", system-ui, -apple-system, "Segoe UI", sans-serif;
  --data: "IBM Plex Mono", ui-monospace, "Cascadia Mono", Consolas, monospace;
}

:root[data-theme="light"] {
  --ink:       #f4f5f8;
  --ink-2:     #ffffff;
  --ink-3:     #eef0f5;
  --rule:      #dfe3ec;
  --chalk:     #131822;
  --chalk-dim: #5a6376;
  --mark:      #a25c00;
}

* { box-sizing: border-box; }

html { background: var(--ink); }

body {
  margin: 0;
  background: var(--ink);
  color: var(--chalk);
  font: 400 17px/var(--step) var(--body);
  -webkit-text-size-adjust: 100%;
  -webkit-font-smoothing: antialiased;

  /* dark ruled paper. One hairline every --step, so the grid the text sits on
     is visible rather than implied. Kept faint on purpose: at full contrast it
     reads as a table, not as paper. */
  background-image: repeating-linear-gradient(
    to bottom,
    transparent 0,
    transparent calc(var(--step) - 1px),
    var(--rule) calc(var(--step) - 1px),
    var(--rule) var(--step)
  );
  background-position: 0 0;
}

.sheet {
  max-width: var(--measure);
  margin: 0 auto;
  padding: calc(var(--step) * 2) 20px calc(var(--step) * 3);
}

a { color: inherit; text-decoration: none; }

:where(a, button):focus-visible {
  outline: 2px solid var(--mark);
  outline-offset: 3px;
  border-radius: 2px;
}

/* --- masthead ------------------------------------------------------------ */

.masthead {
  display: flex;
  align-items: flex-start;
  gap: 16px;
  margin-bottom: var(--step);
}

.masthead-text { flex: 1; min-width: 0; }

.wordmark {
  font: 600 44px/var(--step) var(--display);
  font-variation-settings: "wdth" 96, "opsz" 40;
  letter-spacing: -0.022em;
  margin: 0 0 6px;
}

.thesis {
  margin: 0;
  color: var(--chalk-dim);
  font-size: 15px;
  max-width: 46ch;
}

.thesis b { color: var(--chalk); font-weight: 600; }

.themeToggle {
  flex: none;
  background: var(--ink-2);
  color: var(--chalk-dim);
  border: 1px solid var(--rule);
  border-radius: 999px;
  padding: 5px 13px;
  font: 500 12px/1 var(--data);
  letter-spacing: 0.04em;
  cursor: pointer;
}
.themeToggle:hover { color: var(--chalk); border-color: var(--chalk-dim); }

/* --- countdown ----------------------------------------------------------- */

.till {
  display: flex;
  align-items: baseline;
  gap: 9px;
  margin: 0 0 var(--step);
  padding-bottom: 6px;
  border-bottom: 1px solid var(--rule);
}
.till-n {
  font: 600 30px/1 var(--data);
  color: var(--mark);
  font-variant-numeric: tabular-nums;
}
.till-l { color: var(--chalk-dim); font-size: 13px; }

/* --- section label ------------------------------------------------------- */

.label {
  font: 500 12px/1 var(--data);
  letter-spacing: 0.13em;
  text-transform: uppercase;
  color: var(--chalk-dim);
  margin: 0 0 12px;
}

/* --- the marks map ------------------------------------------------------- */

.map { margin: 0 0 calc(var(--step) * 1.5); }

.mapNote {
  color: var(--chalk-dim);
  font-size: 13px;
  margin: 10px 0 0;
}

.subj {
  display: block;
  padding: 11px 0 13px;
  border-bottom: 1px solid var(--rule);
}
.subj:first-of-type { border-top: 1px solid var(--rule); }
.subj:hover .subj-name,
.subj:focus-visible .subj-name { color: var(--hue, var(--mark)); }

.subj-head {
  display: flex;
  align-items: baseline;
  gap: 10px;
  margin-bottom: 8px;
}
.subj-name {
  font: 600 22px/1.2 var(--display);
  font-variation-settings: "wdth" 92;
  letter-spacing: -0.012em;
  transition: color .14s ease;
}
.subj-meta {
  margin-left: auto;
  font: 400 12px/1 var(--data);
  color: var(--chalk-dim);
  white-space: nowrap;
  font-variant-numeric: tabular-nums;
}

/* the bar: one flex child per unit, width set inline from real marks */
.bar {
  display: flex;
  gap: 2px;
  height: 13px;
  align-items: stretch;
}
.seg {
  background: var(--hue, var(--mark));
  opacity: .34;
  border-radius: 2px;
  transform-origin: left center;
  transition: opacity .14s ease;
}
.seg:nth-child(odd) { opacity: .52; }
.seg-top { opacity: .95; }
.subj:hover .seg, .subj:focus-visible .seg { opacity: .82; }
.subj:hover .seg-top, .subj:focus-visible .seg-top { opacity: 1; }

/* Light is a different surface, not the same one inverted: a tint that reads
   fine on ink disappears on white. Found by loading the page in light and
   watching the marks map vanish.

   These come AFTER the hover rules and restate them, because an added
   [data-theme] attribute raises specificity: written above, ":root[...] .seg"
   (0,2,1) would have beaten ".subj:hover .seg" (0,2,0) and quietly killed
   hover in light mode. Specificity, not order, is what decides - so matching
   pairs have to be restated rather than relying on cascade position. */
:root[data-theme="light"] .seg { opacity: .58; }
:root[data-theme="light"] .seg:nth-child(odd) { opacity: .78; }
:root[data-theme="light"] .seg-top { opacity: 1; }
:root[data-theme="light"] .subj:hover .seg,
:root[data-theme="light"] .subj:focus-visible .seg { opacity: .92; }
:root[data-theme="light"] .ch-n { color: color-mix(in srgb, var(--hue, var(--mark)) 70%, #1b2430); }

@media (prefers-reduced-motion: no-preference) {
  .bar-anim .seg { animation: grow .32s cubic-bezier(.2,.7,.3,1) backwards; }
  @keyframes grow { from { transform: scaleX(0); } to { transform: scaleX(1); } }
}

/* --- subject page -------------------------------------------------------- */

.back {
  display: inline-block;
  color: var(--chalk-dim);
  font: 400 13px/1 var(--data);
  margin-bottom: 18px;
}
.back:hover { color: var(--chalk); }

.grabs {
  display: grid;
  gap: 8px;
  grid-template-columns: repeat(auto-fit, minmax(265px, 1fr));
  margin: 0 0 calc(var(--step) * 1.2);
}
.grab {
  display: block;
  background: var(--ink-2);
  border: 1px solid var(--rule);
  border-radius: 6px;
  padding: 13px 15px;
}
.grab:hover { border-color: var(--hue, var(--mark)); background: var(--ink-3); }
.grab-k { font-weight: 600; font-size: 15px; margin-bottom: 2px; }
.grab-v {
  color: var(--chalk-dim);
  font: 400 12px/1.5 var(--data);
  font-variant-numeric: tabular-nums;
}

.ch {
  display: flex;
  align-items: baseline;
  gap: 13px;
  padding: 9px 2px;
  border-bottom: 1px solid var(--rule);
}
.ch:first-of-type { border-top: 1px solid var(--rule); }
.ch:hover { background: var(--ink-2); }
.ch-n {
  flex: none;
  font: 500 12px/1 var(--data);
  color: var(--hue, var(--mark));
  font-variant-numeric: tabular-nums;
  min-width: 2.4em;
}
.ch-t {
  flex: 1;
  min-width: 0;
  font-size: 15px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.ch-s {
  flex: none;
  font: 400 12px/1 var(--data);
  color: var(--chalk-dim);
  font-variant-numeric: tabular-nums;
}

/* --- colophon ------------------------------------------------------------ */

.colophon {
  margin-top: calc(var(--step) * 2);
  padding-top: 14px;
  border-top: 1px solid var(--rule);
  color: var(--chalk-dim);
  font-size: 13px;
}
.colophon a { color: var(--chalk); text-decoration: underline; text-underline-offset: 3px; }

/* --- narrow -------------------------------------------------------------- */

@media (max-width: 560px) {
  .sheet { padding: calc(var(--step) * 1.2) 16px calc(var(--step) * 2); }
  .wordmark { font-size: 32px; line-height: 1.12; }
  .subj-meta { margin-left: 0; width: 100%; }
  /* the label wrapped under the number and picked up the flex indent */
  .till { flex-wrap: wrap; row-gap: 2px; }
  .till-l { flex: 1 1 100%; }
  .subj-head { flex-wrap: wrap; gap: 4px 10px; }
  .ch-s { display: none; }
}

@media (prefers-reduced-motion: reduce) {
  * { animation: none !important; transition: none !important; }
}

/* --- reader -------------------------------------------------------------- */

.rdTop {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 10px 16px;
  border-bottom: 1px solid var(--rule);
  background: var(--ink);
  position: sticky;
  top: 0;
  z-index: 5;
}
.rdTitle {
  flex: 1;
  min-width: 0;
  font-size: 15px;
  font-weight: 600;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.rdBack, .rdDl {
  flex: none;
  color: var(--chalk-dim);
  font: 400 13px/1 var(--data);
}
.rdBack:hover, .rdDl:hover { color: var(--chalk); }

/* The canvas is the page. No ruled background behind it: the PDF has its own
   paper, and two sets of rules at different pitches reads as a moire. */
.rdStage {
  background: var(--ink);
  background-image: none;
  min-height: 60vh;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 12px;
  padding: 12px 8px 96px;
}
/* Sized before its canvas exists, so the scrollbar is correct from the first
   frame and does not jump as pages render in. */
.pgWrap {
  background: #fff;
  border-radius: 3px;
  box-shadow: 0 2px 18px rgba(0,0,0,.45);
  overflow: hidden;
  flex: none;
}
.pgWrap img { display: block; width: 100%; height: auto; }
body.reading { background-image: none; }

.rdNote {
  text-align: center;
  color: var(--chalk-dim);
  font-size: 13px;
  padding: 10px 16px 0;
  min-height: 28px;
}
.rdNote b { color: var(--mark); }
.rdNote button {
  background: none;
  border: none;
  border-bottom: 1px solid var(--chalk-dim);
  color: var(--chalk);
  font: inherit;
  cursor: pointer;
  padding: 0;
}

.rdBar {
  position: fixed;
  left: 50%;
  transform: translateX(-50%);
  bottom: 16px;
  display: flex;
  align-items: center;
  gap: 6px;
  padding: 6px;
  background: var(--ink-2);
  border: 1px solid var(--rule);
  border-radius: 999px;
  box-shadow: 0 4px 22px rgba(0,0,0,.5);
  z-index: 6;
}
.rdBar button {
  background: none;
  border: none;
  color: var(--chalk);
  font: 500 15px/1 var(--data);
  cursor: pointer;
  border-radius: 999px;
  padding: 8px 15px;
  min-width: 44px;
  min-height: 40px;
}
.rdBar button:hover:not(:disabled) { background: var(--ink-3); }
.rdBar button:disabled { color: var(--chalk-dim); opacity: .45; cursor: default; }
.rdCount {
  font: 500 13px/1 var(--data);
  color: var(--chalk-dim);
  font-variant-numeric: tabular-nums;
  padding: 0 4px;
  white-space: nowrap;
}
.rdCount b { color: var(--chalk); font-weight: 600; }

/* progress pip on a chapter row, filled in from localStorage */
.ch-at {
  flex: none;
  font: 400 11px/1 var(--data);
  color: var(--mark);
  font-variant-numeric: tabular-nums;
}
.ch-dl {
  flex: none;
  color: var(--chalk-dim);
  font: 400 11px/1 var(--data);
  padding: 2px 5px;
  border: 1px solid var(--rule);
  border-radius: 4px;
}
.ch-dl:hover { color: var(--chalk); border-color: var(--chalk-dim); }

/* --- practice questions -------------------------------------------------- */

.qCard {
  border: 1px solid var(--rule);
  border-radius: 8px;
  background: var(--ink-2);
  padding: 14px 15px 12px;
  margin: 0 0 12px;
}
.qStem { margin: 0 0 11px; font-size: 15.5px; line-height: 1.5; }
.qN {
  display: inline-block;
  min-width: 2em;
  color: var(--hue, var(--mark));
  font: 500 12px/1 var(--data);
  vertical-align: 2px;
}
.opt {
  display: block;
  width: 100%;
  text-align: left;
  background: var(--ink);
  color: var(--chalk);
  border: 1px solid var(--rule);
  border-radius: 7px;
  padding: 9px 12px;
  margin: 0 0 7px;
  font: 400 14.5px/1.45 var(--body);
  cursor: pointer;
}
.opt:hover:not(:disabled) { border-color: var(--hue, var(--mark)); }
.opt:disabled { cursor: default; }
.optK {
  display: inline-block;
  min-width: 1.7em;
  color: var(--chalk-dim);
  font: 500 12px/1 var(--data);
}
/* Correct is stated, not just coloured: colour alone fails for a colourblind
   reader and in a screenshot. */
.opt.is-right {
  border-color: #5fb87a;
  background: color-mix(in srgb, #5fb87a 16%, var(--ink));
}
.opt.is-right .optK::after { content: " correct"; color: #5fb87a; }
.opt.is-wrong {
  border-color: #d9636b;
  background: color-mix(in srgb, #d9636b 14%, var(--ink));
}
.opt.is-wrong .optK::after { content: " your answer"; color: #d9636b; }
.why {
  margin: 9px 0 0;
  padding-top: 9px;
  border-top: 1px dashed var(--rule);
  color: var(--chalk-dim);
  font-size: 13.5px;
  line-height: 1.5;
}
.why b { color: var(--chalk); }
.quizBar {
  display: flex;
  align-items: baseline;
  gap: 12px;
  margin: 0 0 16px;
  padding-bottom: 8px;
  border-bottom: 1px solid var(--rule);
}
#score { font: 400 13px/1.4 var(--data); color: var(--chalk-dim); }
#reset {
  margin-left: auto;
  background: none;
  border: 1px solid var(--rule);
  border-radius: 999px;
  color: var(--chalk-dim);
  font: 500 11px/1 var(--data);
  padding: 6px 11px;
  cursor: pointer;
}
#reset:hover { color: var(--chalk); border-color: var(--chalk-dim); }

/* Where a question came from. The two pools are not equal evidence - one is
   what the board asked, the other is drill built from our own notes - so the
   card says which, in words, and the board ones carry an accent edge. Said in
   text and not only in colour, for the same reason as is-right above. */
.qTag {
  margin: 0 0 7px;
  font: 500 10.5px/1 var(--data);
  letter-spacing: .07em;
  text-transform: uppercase;
  color: var(--chalk-dim);
}
.qCard.is-board {
  border-left: 3px solid var(--hue, var(--mark));
  padding-left: 13px;
}
.qCard.is-board .qTag { color: var(--hue, var(--mark)); }

/* The seam between one pass through the pool and the next. */
.qRound {
  margin: 22px 0 12px;
  padding-top: 12px;
  border-top: 1px solid var(--rule);
  color: var(--chalk-dim);
  font: 500 11px/1.4 var(--data);
  letter-spacing: .05em;
  text-transform: uppercase;
}
/* The scroll sentinel. It has to have height, or it can sit exactly on the
   observer root edge and never report as intersecting. */
.qMore { height: 1px; }
.qMoreBtn {
  display: block;
  margin: 16px auto 0;
  background: none;
  border: 1px solid var(--rule);
  border-radius: 999px;
  color: var(--chalk-dim);
  font: 500 11px/1 var(--data);
  padding: 9px 16px;
  cursor: pointer;
}
.qMoreBtn:hover { color: var(--chalk); border-color: var(--chalk-dim); }

.provenance {
  color: var(--chalk-dim);
  font-size: 12.5px;
  margin: 20px 0 0;
  padding-top: 12px;
  border-top: 1px solid var(--rule);
}
