/* TeacherKit — the page IS the whiteboard.
   Design language: Pall (tokens lifted 1:1 from pal-site/styles.css :root, so the
   two products read as one family) — white · Apple near-black · Apple blue, the
   8pt grid, and Notion (ni_*) icons rather than SF Symbols. Board handwriting
   stays ui-rounded. Motion: one spring curve, used sparingly. */
:root {
  /* --- Pall tokens (canonical names) --- */
  --font-serif: ui-serif, "New York", "Iowan Old Style", "Apple Garamond", Georgia, "Times New Roman", serif;
  --font-sans: -apple-system, BlinkMacSystemFont, "SF Pro Display", "SF Pro Text", "SF Pro Icons", system-ui, "Helvetica Neue", Helvetica, Arial, sans-serif;
  --font-mono: ui-monospace, "SF Mono", "SFMono-Regular", Menlo, Monaco, "Cascadia Mono", monospace;

  --paper: #ffffff;          /* the sheet */
  --ink: #1d1d1f;            /* Apple near-black — text & icons */
  --muted: #6e6e73;          /* Apple secondary grey */
  --faint: #86868b;          /* Apple tertiary grey */
  --line: #d2d2d7;           /* Apple hairline */
  --line-2: #e8e8ed;
  --accent: #0071e3;         /* Apple blue — buttons, links, the teacher's mark */
  --accent-hover: #0077ed;
  --accent-press: #006edb;
  --on-accent: #ffffff;
  --r-pill: 980px;

  /* Status colours. Named once, because the same state was being painted two
     different greens (#1db954 on the home page, #1d9e54 on the homework page)
     and two different reds — the palette drifted per file. These are outside
     the white/ink/blue brand palette by necessity: "doğru", "yanlış" and
     "bağlantı yok" have to be legible as states, not as brand. */
  --good: #1d9e54;  --good-soft: rgba(29, 158, 84, 0.10);
  --bad:  #b3261e;  --bad-soft:  rgba(179, 38, 30, 0.08);
  --warn: #a35b00;  --warn-dot:  #e8a33d;

  /* Spacing — 8pt grid */
  --s-1: 4px;  --s-2: 8px;  --s-3: 12px; --s-4: 16px; --s-5: 24px;
  --s-6: 32px; --s-7: 48px; --s-8: 64px;

  /* --- THE TYPE SCALE, whole, from Apple's iOS table (Large, 17pt default) ---
     It was previously three sizes (body/small/xs) plus a dozen one-off px values
     invented per page — and one class, .bh, defined at two different sizes in two
     different files, where load order decided which one a page got. Hierarchy is
     built from THIS ladder and from weight, never from a new number.
     Weights are Regular/Semibold/Bold only: HIG says avoid the thin end, and 550
     and 650 were being used as if they were steps on a scale. */
  --t-large-title: 34px; --lh-large-title: 41px;
  --t-title-1: 28px;     --lh-title-1: 34px;
  --t-title-2: 22px;     --lh-title-2: 28px;
  --t-title-3: 20px;     --lh-title-3: 25px;
  --t-headline: 17px;    --lh-headline: 22px;
  --t-callout: 16px;     --lh-callout: 21px;
  --t-subhead: 15px;     --lh-subhead: 20px;
  --t-footnote: 13px;    --lh-footnote: 18px;
  --t-caption: 12px;     --lh-caption: 16px;

  /* The three original names, kept as aliases onto the ladder they already sat
     on (17/15/13 = Body/Subhead/Footnote), so no existing rule shifts. */
  --t-body: var(--t-headline); --t-small: var(--t-subhead); --t-xs: var(--t-footnote);

  /* The smallest a finger can reliably hit (HIG: 44×44pt). Anything a person is
     meant to tap gets at least this, however small it looks. */
  --tap: 44px;

  /* --- TeacherKit aliases onto the Pall scale (existing rules keep working) --- */
  --ink-2: var(--muted);
  --ink-3: var(--faint);
  --hairline: var(--line-2);
  /* One glass material, shared by the orb and every shape it becomes — so the
     morph never crossfades between two different-looking surfaces. */
  --glass-fill: rgba(255, 255, 255, 0.55);
  --glass-edge: rgba(255, 255, 255, 0.75);
  --glass-shadow: 0 12px 40px rgba(29, 29, 31, 0.16);
  --blue: var(--accent);
  --blue-soft: rgba(0, 113, 227, 0.10);
  --spring: cubic-bezier(0.32, 0.72, 0, 1);
  --sans: var(--font-sans);
  --hand: ui-rounded, "SF Pro Rounded", -apple-system, BlinkMacSystemFont, sans-serif;
  color-scheme: light;
}

/* ---- ONE FACE FOR EVERY TITLE -------------------------------------------
   style.css has always DECLARED --font-serif and never once used it. So the
   marketing site set its headings in New York and the app set the very same
   words in the system sans: two halves of one product disagreeing about what
   TeacherKit looks like, on pages a student moves between in a single tap.
   Titles are the thing you recognise a product by, so they are set here, once,
   for every page that loads this sheet. Body text stays sans on purpose —
   New York is a display face, and a paragraph set in it is harder to read. */
h1, h2, h3,
.gtitle, .bq, .bh, .dtitle, .dsec, .bdoneline,
.sheet-card h2, .phead h1, .widget .big {
  font-family: var(--font-serif);
  letter-spacing: -0.018em;
}

/* ---------- Notion (ni_*) icons — black template PNGs, never SF Symbols ---------- */
.ni {
  width: 20px; height: 20px; display: block;
  object-fit: contain;
  /* The PNGs ship black; state is carried by opacity, never by recolouring. */
  opacity: 0.82; transition: opacity 0.2s, transform 0.35s var(--spring);
}
.ni-lg { width: 26px; height: 26px; }
.ni-sm { width: 16px; height: 16px; }
* { box-sizing: border-box; margin: 0; padding: 0; }
html, body { height: 100%; }
body {
  font-family: var(--sans);
  /* HIG Body, bound once. Nothing set a base size, so every element that did not
     declare one inherited the browser's 16px default and sat just off the scale
     the rest of the app is drawn on. rem stays root-relative, so no existing
     rem/var(--t-*) size shifts. */
  font-size: 17px;
  line-height: 1.47;
  background: var(--paper);
  color: var(--ink);
  -webkit-font-smoothing: antialiased;
  overflow: hidden;
}
button {
  font: inherit; border: 0; cursor: pointer; background: var(--blue); color: #fff;
  border-radius: 980px; padding: 12px 28px; font-size: 17px; font-weight: 600;
  transition: transform 0.35s var(--spring), opacity 0.2s;
}
button:hover { transform: scale(1.03); }
button:active { transform: scale(0.97); }
button:focus-visible, input:focus-visible { outline: 3px solid var(--blue); outline-offset: 3px; }
button.quiet { background: none; color: var(--blue); font-weight: 500; }

/* ---------- top bar: whisper-thin ---------- */
#top {
  position: fixed; inset: 0 0 auto 0; height: 52px; z-index: 20;
  display: flex; align-items: center; justify-content: space-between;
  padding: 0 20px; background: rgba(255, 255, 255, 0.72); backdrop-filter: blur(28px) saturate(180%); -webkit-backdrop-filter: blur(28px) saturate(180%);
}
#top .title { font-size: 14px; font-weight: 600; letter-spacing: -0.01em; }
#top .title span { color: var(--ink-2); font-weight: 400; }
#clock { font-size: 14px; font-variant-numeric: tabular-nums; color: var(--ink-2); }
#clock.low { color: var(--blue); font-weight: 600; }
#progress { position: absolute; left: 0; bottom: 0; height: 2px; background: var(--blue); width: 0%; transition: width 1s linear; }

/* ---------- the board ---------- */
#board {
  position: absolute; inset: 52px 0 0 0; overflow-y: auto; scroll-behavior: smooth;
  padding: 40px max(24px, calc(50vw - 440px)) 240px;
}
.section { margin: 0 0 40px; }
.section h2 {
  font-family: var(--hand); font-size: 28px; font-weight: 700; letter-spacing: -0.02em;
  margin: 0; padding-bottom: 2px;
}
/* Pall scribble instead of a border-bottom — the heading gets underlined, drawn. */
.section .scribble { height: 22px; width: 140px; margin: -2px 0 12px -6px; pointer-events: none; opacity: 0.5; }
.section .scribble svg { width: 100% !important; height: 100% !important; overflow: visible; }
.section:not(:has(.scribble)) h2 { padding-bottom: 8px; border-bottom: 1px solid var(--hairline); margin-bottom: 16px; }
.block { margin: 0 0 16px; opacity: 0; transform: translateY(6px); transition: opacity 0.5s var(--spring), transform 0.5s var(--spring); }
.block.in { opacity: 1; transform: none; }
.block.w-title { font-family: var(--hand); font-size: 34px; font-weight: 800; letter-spacing: -0.02em; }
.block.w-heading { font-family: var(--hand); font-size: 22px; font-weight: 700; }
.block.w-body { font-family: var(--hand); font-size: 19px; line-height: 1.55; }
.block.w-em { font-family: var(--hand); font-size: 19px; line-height: 1.5; color: var(--blue); font-weight: 600; }
.block.w-formula {
  font-family: var(--hand); font-size: 24px; font-weight: 600; text-align: center;
  padding: 16px; background: var(--blue-soft); border-radius: 16px;
}
.block.sketch { text-align: center; }
.block.sketch svg { max-width: 100%; height: auto; }
.block.sketch .cap { font-size: 13px; color: var(--ink-2); margin-top: 8px; }
.block.file {
  display: flex; align-items: center; gap: 12px; padding: 12px 16px;
  border: 1px solid var(--hairline); border-radius: 16px; font-size: 15px;
}
.block.file .ico { width: 32px; height: 32px; border-radius: 8px; background: var(--blue-soft); color: var(--blue); display: grid; place-items: center; font-weight: 700; font-size: 11px; }
.caret { display: inline-block; width: 8px; height: 8px; margin-left: 2px; border-radius: 50%; background: var(--blue); vertical-align: baseline; animation: caret 1s infinite; }
@keyframes caret { 50% { opacity: 0.2; } }
.hl { animation: hlpulse 1.6s var(--spring); border-radius: 8px; }
@keyframes hlpulse { 0% { background: var(--blue-soft); } 100% { background: transparent; } }
@keyframes tk-draw { to { stroke-dashoffset: 0; } }
.section.out, .block.out { opacity: 0; transform: translateY(-6px); transition: opacity 0.4s, transform 0.4s; }
.block.q-rec { display: flex; gap: 10px; align-items: baseline; font-family: var(--hand); font-size: 17px; color: var(--ink-2); }
/* Verdict = a Notion icon, black (Pall rule); "wrong" simply sits back. */
.block.q-rec .mark { display: inline-flex; align-self: center; }
.block.q-rec .mark .ni { opacity: 0.9; }
.block.q-rec .mark.wrong .ni, .block.q-rec .mark.skipped .ni { opacity: 0.4; }

/* ---------- teacher orb — Pall's Live orb, copied faithfully ----------
   PallSkip ContentView.swift liveOrb: solid accent circle, ni_guides_2 glyph in
   the background colour, and LivePulse — two soft rings radiating out (easeOut
   1.4s, staggered 0.7s, scale 0.8→1.3, opacity 0.6→0) while listening. */
/* The orb is the room's ONE elastic body: a clear glass bead that swells into
   whatever the lesson needs (a question, a deck, a spotlight) and shrinks back.
   Deliberately NOT a blue disc — colour belongs to what the teacher DRAWS, so the
   container stays clear and the board keeps the only accent on screen. */
#orb {
  position: fixed; left: 24px; bottom: 24px; z-index: 30;
  width: 72px; height: 72px; border-radius: 50%;
  background: var(--glass-fill);
  backdrop-filter: blur(30px) saturate(180%); -webkit-backdrop-filter: blur(30px) saturate(180%);
  border: 1px solid var(--glass-edge);
  box-shadow: var(--glass-shadow), inset 0 1px 0 rgba(255, 255, 255, 0.7);
  transform: scale(var(--amp, 1));
  transition: transform 0.12s ease-out, box-shadow 0.4s, opacity 0.2s;
  display: grid; place-items: center;
}
/* The glyph: Pall renders ni_guides_2 in the background colour on the accent orb
   (NIcon color backgroundDeep). Mask keeps the template-PNG discipline. */
#orb::after {
  content: ''; width: 26px; height: 26px; background: var(--ink); opacity: 0.7;
  -webkit-mask: url('./icons/ni_guides_2.png') center / contain no-repeat;
          mask: url('./icons/ni_guides_2.png') center / contain no-repeat;
}
/* Once the character is mounted (face.js) it IS the glyph — the static icon
   steps aside. Pages that never mount a face keep the icon. */
#orb.hasface::after { display: none; }
#orb .facesvg {
  position: absolute; inset: 0; width: 100%; height: 100%;
  overflow: visible; pointer-events: none;
}
#orb.connecting { animation: breathe 1.1s ease-in-out infinite; opacity: 0.5; }
@keyframes breathe { 50% { transform: scale(1.06); } }
/* LivePulse rings (both reuse the pall-ring keyframes; second is delayed 0.7s) */
#orb .ring, #orb::before {
  content: ''; position: absolute; inset: 0; border-radius: 50%;
  border: 2px solid rgba(29, 29, 31, 0.28); opacity: 0; pointer-events: none;
}
#orb.listening .ring { animation: pall-ring 1.4s ease-out infinite; }
#orb.listening::before { animation: pall-ring 1.4s ease-out 0.7s infinite; }
@keyframes pall-ring { 0% { transform: scale(0.8); opacity: 0.6; } 100% { transform: scale(1.3); opacity: 0; } }
#orb.reconnect .ring { border-color: var(--blue); animation: ring 1.2s ease-out infinite; }
@keyframes ring { 0% { transform: scale(0.9); opacity: 0.7; } 100% { transform: scale(1.25); opacity: 0; } }
/* While an overlay card is open the orb has BECOME the card (morph) — hidden,
   not faded alongside: the morph layer owns the transition. */
#orb.absorbed { opacity: 0; pointer-events: none; }

/* ---------- live captions: Apple TV subtitle style, word by word ----------
   Matched to the reference frame: ONE near-black rounded box wrapping the whole
   text block (not per-line — the left edge stays flush across lines), pure white
   text, small radius, centred, tight leading. Speaker is carried by italics, the
   subtitle convention, rather than by colour. */
#caption {
  position: fixed; left: 50%; transform: translateX(-50%); bottom: 104px; z-index: 25;
  width: min(900px, calc(100vw - 80px)); text-align: center; pointer-events: none;
  font-size: clamp(20px, 1.8vw, 28px); line-height: 1.34; font-weight: 550;
  letter-spacing: -0.005em; text-wrap: balance;
  opacity: 0; transition: opacity 0.2s;
}
#caption.on { opacity: 1; }
#caption .line {
  display: inline-block;                 /* one box, sized to the widest line */
  background: rgba(0, 0, 0, 0.78);
  color: #fff;
  padding: 0.30em 0.62em 0.34em;
  border-radius: 8px;
  text-shadow: 0 1px 2px rgba(0, 0, 0, 0.35);
}
#caption .line.student { font-style: italic; }   /* the other speaker, subtitle-style */
#caption .cw { display: inline-block; animation: cw-in 0.16s ease-out both; }
#caption .cw.hot { animation: cw-in 0.16s ease-out both; }
@keyframes cw-in { from { opacity: 0; } to { opacity: 1; } }
@media (prefers-reduced-motion: reduce) { #caption .cw { animation: none; } }

/* ---------- student cam ---------- */
#cam {
  position: fixed; right: 24px; bottom: 24px; z-index: 30;
  width: 148px; aspect-ratio: 3/4; border-radius: 20px; overflow: hidden;
  box-shadow: 0 8px 40px rgba(29, 29, 31, 0.18); background: var(--ink);
  transition: transform 0.5s var(--spring);
}
#cam video { width: 100%; height: 100%; object-fit: cover; transform: scaleX(-1); }

/* ---------- question card ---------- */
/* Overlay cards are NOT panels that fade in somewhere else — they are the orb,
   grown. They share its corner, its material and its origin, so the only thing
   that ever animates is SHAPE. No opacity on the container: it is staged
   invisible (.morph-stage) while the morph layer physically stretches the orb
   into this rectangle, then pinned exactly where the morph ended. Only the
   card's CHILDREN fade, so the body itself reads as one continuous substance. */
#qcard {
  position: fixed; left: 24px; bottom: 24px; z-index: 40;
  transform-origin: 0 100%; transform: scale(0.14); visibility: hidden; pointer-events: none;
  width: min(520px, calc(100vw - 48px));
  background: var(--glass-fill);
  backdrop-filter: blur(30px) saturate(180%); -webkit-backdrop-filter: blur(30px) saturate(180%);
  border: 1px solid var(--glass-edge); border-radius: 28px;
  padding: 24px 28px; box-shadow: var(--glass-shadow);
  transition: transform 0.55s var(--spring);
}
#qcard.show { transform: scale(1); visibility: visible; }
#qcard .k { font-size: 12px; font-weight: 700; letter-spacing: 0.08em; text-transform: uppercase; color: var(--blue); margin-bottom: 8px; }
#qcard .q { font-family: var(--hand); font-size: 21px; font-weight: 600; line-height: 1.4; }
#qcard .choices { margin-top: 14px; display: flex; flex-wrap: wrap; gap: 8px; }
#qcard .choices span { padding: 8px 16px; border: 1px solid var(--hairline); border-radius: 980px; font-size: 15px; }
#qcard.correct { border-color: var(--blue); }
#qcard .verdict { margin-top: 12px; font-size: 15px; font-weight: 600; color: var(--blue); }

/* ---------- the teacher's finger (board_point) ---------- */
/* Lives inside the sketch's own <svg>, so it is in the model's coordinates and
   scales with the drawing. fill-box origin makes the ping pulse about the dot. */
.tk-point-ring {
  fill: none; stroke: var(--blue); stroke-width: 2.5;
  transform-box: fill-box; transform-origin: center;
  animation: tk-ping 1.9s cubic-bezier(0.32, 0.72, 0, 1) infinite;
}
.tk-point-dot { fill: var(--blue); transform-box: fill-box; transform-origin: center; animation: tk-point-dot 1.9s ease-out infinite; }
.tk-point-label {
  fill: var(--blue); font-family: var(--hand); font-weight: 700;
  paint-order: stroke; stroke: #fff; stroke-width: 3px; stroke-linejoin: round;
}
@keyframes tk-ping {
  0%   { opacity: 0.85; transform: scale(0.45); }
  70%  { opacity: 0;    transform: scale(1.6); }
  100% { opacity: 0;    transform: scale(1.6); }
}
@keyframes tk-point-dot {
  0%, 100% { opacity: 0.95; transform: scale(1); }
  50%      { opacity: 0.65; transform: scale(0.86); }
}
/* ---------- shimmer: a light travelling THROUGH the ink, left → right ---------- */
/* Words: the gradient is clipped to the glyphs, so the sweep never leaves the
   letters. Drawings do this in SVG instead (a gradient band on cloned strokes). */
.block.shimmer-text {
  background-image: linear-gradient(100deg, var(--ink) 42%, #ffffff 50%, var(--ink) 58%);
  background-size: 260% 100%;
  background-clip: text; -webkit-background-clip: text;
  -webkit-text-fill-color: transparent; color: transparent;
  animation: tk-shimmer 1.7s ease-in-out 1;
}
.block.shimmer-text.loop { animation-iteration-count: infinite; }
.block.w-em.shimmer-text, .block.w-formula.shimmer-text {
  background-image: linear-gradient(100deg, var(--accent) 42%, #ffffff 50%, var(--accent) 58%);
}
@keyframes tk-shimmer { from { background-position: 130% 0; } to { background-position: -30% 0; } }
@media (prefers-reduced-motion: reduce) { .block.shimmer-text { animation: none; } }

/* Pointing at a written line lights the line itself. */
.block.lit {
  background: var(--blue-soft); border-radius: 12px;
  box-shadow: 0 0 0 8px var(--blue-soft);
  transition: background 0.35s var(--spring), box-shadow 0.35s var(--spring);
}
@media (prefers-reduced-motion: reduce) {
  .tk-point-ring, .tk-point-dot { animation: none; opacity: 0.9; }
}

/* ---------- orb→card morph: overlays RESHAPE out of the orb, never fade ---------- */
#tkmorph {
  position: fixed; z-index: 45; pointer-events: none;
  background: var(--glass-fill);
  backdrop-filter: blur(30px) saturate(180%); -webkit-backdrop-filter: blur(30px) saturate(180%);
  border: 1px solid var(--glass-edge);
  box-shadow: var(--glass-shadow);
  will-change: transform, width, height, border-radius, background;
}
/* While morphing, the card frame is visible but its CONTENT is not yet: the
   container never fades — only its children materialise after the reshape. */
.morph-stage { visibility: hidden !important; }
.morph-in { transition: none !important; transform: none !important; visibility: visible !important; }
.morph-in > * { animation: morph-content 0.28s ease both; }
@keyframes morph-content { from { opacity: 0; } to { opacity: 1; } }

/* ---------- generic cards (flash / blank / match / spotlight) ---------- */
#gcard {
  position: fixed; left: 24px; bottom: 24px; z-index: 40;
  transform-origin: 0 100%; transform: scale(0.13); visibility: hidden; pointer-events: none;
  width: min(560px, calc(100vw - 48px));
  background: var(--glass-fill);
  backdrop-filter: blur(34px) saturate(180%); -webkit-backdrop-filter: blur(34px) saturate(180%);
  border: 1px solid var(--glass-edge); border-radius: 28px;
  padding: 22px 28px 24px; box-shadow: var(--glass-shadow);
  transition: transform 0.55s var(--spring);
  text-align: center;
}
#gcard.show { transform: scale(1); visibility: visible; }
#gcard .k { font-size: 12px; font-weight: 700; letter-spacing: 0.08em; text-transform: uppercase; color: var(--blue); margin-bottom: 12px; }
#gcard .flipper { perspective: 900px; }
#gcard .flipinner {
  position: relative; min-height: 110px; transform-style: preserve-3d;
  transition: transform 0.55s var(--spring);
}
#gcard .flipinner.noanim { transition: none; }
#gcard .flipinner.flip { transform: rotateX(180deg); }
#gcard .face {
  position: absolute; inset: 0; display: grid; place-items: center;
  backface-visibility: hidden; border-radius: 16px; padding: 16px 20px;
  font-family: var(--hand); font-size: 24px; font-weight: 700; line-height: 1.35;
}
#gcard .face.front { background: var(--blue-soft); }
#gcard .face.back { transform: rotateX(180deg); background: var(--blue); color: #fff; }
#gcard .dots { display: flex; gap: 6px; justify-content: center; margin-top: 14px; }
#gcard .dot { width: 6px; height: 6px; border-radius: 50%; background: var(--ink-3); transition: transform 0.3s var(--spring), background 0.3s; }
#gcard .dot.on { background: var(--blue); transform: scale(1.35); }
#gcard .blankline { font-family: var(--hand); font-size: 23px; font-weight: 600; line-height: 1.6; }
#gcard .box {
  display: inline-block; min-width: 76px; height: 1.5em; vertical-align: middle;
  border-bottom: 3px solid var(--blue); margin: 0 6px; border-radius: 4px 4px 0 0;
  background: var(--blue-soft); padding: 0 10px; color: var(--blue); font-weight: 800;
  transition: background 0.4s;
}
#gcard .box.filled { animation: fillpop 0.5s var(--spring); }
@keyframes fillpop { 0% { transform: scale(0.85); } 60% { transform: scale(1.08); } 100% { transform: scale(1); } }
#gcard .matchgrid { display: grid; grid-template-columns: 1fr 1fr; gap: 10px 24px; }
#gcard .col { display: grid; gap: 8px; }
#gcard .chip {
  padding: 10px 14px; border: 1px solid var(--hairline); border-radius: 14px;
  font-family: var(--hand); font-size: 16px; font-weight: 600; position: relative;
  transition: border-color 0.3s, background 0.3s;
}
#gcard .chip.matched { border-color: var(--blue); background: var(--blue-soft); }
#gcard .chip .badge {
  position: absolute; top: -8px; left: -8px; width: 20px; height: 20px; border-radius: 50%;
  background: var(--blue); color: #fff; font-size: 11px; display: grid; place-items: center;
  animation: fillpop 0.4s var(--spring);
}
/* Spotlight used to centre itself on screen. It no longer may: every shape the
   orb takes has to come out of the SAME corner, or the body appears to teleport
   between forms. It only grows wider and taller than the others. */
#gcard[data-kind="spotlight"] { width: min(640px, calc(100vw - 48px)); }
#gcard .big { font-family: var(--hand); font-size: 34px; font-weight: 800; letter-spacing: -0.02em; line-height: 1.25; padding: 8px 4px 4px; }

/* ---------- veils (join / ended / error) ---------- */
.veil {
  position: fixed; inset: 0; z-index: 100; background: var(--paper);
  display: grid; place-items: center; text-align: center; padding: 24px;
  transition: opacity 0.6s var(--spring);
}
.veil.gone { opacity: 0; pointer-events: none; }
.veil .inner { max-width: 420px; display: grid; gap: 16px; justify-items: center; }
.veil h1 { font-family: var(--hand); font-size: 40px; font-weight: 800; letter-spacing: -0.02em; }
.veil p { font-size: 17px; color: var(--ink-2); line-height: 1.5; }
.veil .dot { width: 96px; height: 96px; border-radius: 50%; background: var(--accent); box-shadow: 0 12px 48px rgba(0, 113, 227, 0.28); position: relative; }
/* Pall layered avatar (shared: veil, notes; book.css duplicates for /book). */
.pall-avatar { position: absolute; inset: 0; }
.pall-avatar img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: contain; }
/* A booked student's character takes the veil's face (rounded, over the accent). */
.veil .dot.has-avatar { background: var(--blue-soft); overflow: hidden; }
.veil .dot.has-avatar .pall-avatar img { object-fit: contain; }

/* ---------- drop overlay (Phase 5) ---------- */
#drop {
  position: fixed; inset: 12px; z-index: 90; border: 2px dashed var(--blue); border-radius: 24px;
  background: rgba(255, 255, 255, 0.85); backdrop-filter: blur(8px);
  display: none; place-items: center; font-family: var(--hand); font-size: 24px; font-weight: 700; color: var(--blue);
}
#drop.on { display: grid; }

/* ---------- control strip ---------- */
#ctrls {
  position: fixed; left: 50%; bottom: 24px; transform: translateX(-50%); z-index: 35;
  display: flex; gap: 10px; padding: 8px; border-radius: 980px;
  background: rgba(255, 255, 255, 0.68); backdrop-filter: blur(28px) saturate(180%); -webkit-backdrop-filter: blur(28px) saturate(180%);
  border: 0.5px solid rgba(255, 255, 255, 0.9); box-shadow: 0 8px 32px rgba(29, 29, 31, 0.12), inset 0 0 0 0.5px rgba(29, 29, 31, 0.06);
}
.ctl {
  width: 44px; height: 44px; padding: 0; border-radius: 50%;
  background: none; color: var(--ink-2); display: grid; place-items: center;
}
.ctl:hover { color: var(--ink); transform: scale(1.06); }
.ctl:hover .ni { opacity: 1; }
/* Active control: the icon stays BLACK (Pall rule) — the pill behind it carries
   the state, so a white-on-blue glyph never has to be a second icon file. */
.ctl.on { background: var(--blue-soft); }
.ctl.on .ni { opacity: 1; }
.ctl.on::after {
  content: ''; position: absolute; margin-top: 30px;
  width: 4px; height: 4px; border-radius: 50%; background: var(--accent);
}
.ctl { position: relative; }

/* ---------- push-to-talk ---------- */
#ptthint {
  position: fixed; left: 50%; bottom: 84px; transform: translateX(-50%); z-index: 34;
  font-size: 13px; color: var(--ink-2); background: rgba(255, 255, 255, 0.9);
  backdrop-filter: blur(12px); border: 1px solid var(--hairline);
  padding: 6px 14px; border-radius: 980px;
}
#ptthint b { color: var(--blue); }
body.ptt-held #orb { box-shadow: 0 8px 40px rgba(0, 113, 227, 0.55); }
#toast {
  position: fixed; top: 68px; left: 50%; transform: translateX(-50%); z-index: 60;
  display: flex; gap: 8px; align-items: center; max-width: min(560px, calc(100vw - 32px));
  background: rgba(255, 255, 255, 0.94); backdrop-filter: blur(24px);
  border: 1px solid var(--hairline); border-radius: 18px; padding: 12px 8px 12px 18px;
  box-shadow: 0 16px 56px rgba(29, 29, 31, 0.14); font-size: 14.5px;
  animation: toast-in 0.6s var(--spring);
}
@keyframes toast-in { from { opacity: 0; transform: translateX(-50%) translateY(-10px); } }
#toast .quiet { padding: 8px 12px; font-size: 14px; white-space: nowrap; }

/* ---------- student pen layer ---------- */
#penlayer { position: fixed; inset: 52px 0 0 0; z-index: 15; cursor: crosshair; touch-action: none; }
#penlayer svg { width: 100%; height: 100%; display: block; }
#penlayer polyline { fill: none; stroke: var(--blue); stroke-width: 3; stroke-linecap: round; stroke-linejoin: round; }
body.pen-on #board { pointer-events: none; }

/* ---------- board file/image blocks ---------- */
.block.image img { max-width: min(100%, 480px); border-radius: 16px; box-shadow: 0 8px 32px rgba(29, 29, 31, 0.12); }
.block.sketch.student { border-left: 3px solid var(--blue); padding-left: 16px; }
.block.sketch.student::after { content: 'öğrenci'; display: block; font-size: 11px; color: var(--blue); margin-top: 4px; letter-spacing: 0.06em; text-transform: uppercase; }

@media (max-width: 700px) {
  #board { padding: 32px 20px 200px; }
  #cam { width: 104px; }
  #caption { right: 140px; }
}
@media (prefers-reduced-motion: reduce) {
  * { animation: none !important; transition: none !important; }
}

/* ---------- shared documents on the board (PDF pages, homework sheets) ---------- */
/* The page image and the annotation layer sit in ONE box; the layer's viewBox is
   the page's own coordinate space, so a mark lands exactly where it was drawn at
   any zoom, and page changes swap only the image + that page's marks. */
.block.doc { text-align: center; }
.block.doc .docwrap {
  position: relative; display: block; width: 100%; max-width: 720px; margin: 0 auto;
  border-radius: 14px; overflow: hidden; background: #fff;
  box-shadow: 0 8px 32px rgba(29, 29, 31, 0.12), inset 0 0 0 0.5px rgba(29, 29, 31, 0.08);
}
.block.doc .docimg { display: block; width: 100%; height: 100%; object-fit: contain; }
.block.doc .doclayer { position: absolute; inset: 0; width: 100%; height: 100%; pointer-events: none; overflow: visible; }
.block.doc .doclayer .anno [pathLength] { stroke: var(--ink); }
.block.doc .doclayer .anno.student [pathLength] { stroke: var(--accent); }
.block.doc .cap { font-size: 13px; color: var(--ink-2); margin-top: 8px; font-variant-numeric: tabular-nums; }

/* Visually hidden, still read aloud — for labels a sighted user gets from
   context but a screen reader would otherwise never hear. */
.sr-only {
  position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}

/* The `hidden` attribute must always win. Any author rule that sets `display`
   on an element (`.grid { display: grid }`, `.hh { display: flex }`,
   `.whostrip { display: flex }`) outranks the UA's `[hidden] { display: none }`,
   so `el.hidden = true` silently does nothing and the "hidden" block stays on
   screen. This is one line instead of remembering it at every call site. */
[hidden] { display: none !important; }

/* A draw question has ONE surface. The figure (graph paper, axes, a shape to
   copy) sits behind the canvas the student actually draws on, instead of
   floating above it as a second, un-drawable picture. */
.padstack { position: relative; }
.padstack > .padbg { position: absolute; inset: 0; width: 100%; height: 100%; pointer-events: none; }
.padstack > canvas.pad { position: relative; background: transparent; }

/* --- home: payment banner, upcoming-lessons list, booking entry --- */
.paybanner {
  background: rgba(0, 113, 227, 0.08); color: var(--accent);
  border: 1px solid rgba(0, 113, 227, 0.25); border-radius: 14px;
  padding: 12px 16px; margin: 0 0 14px; font-weight: 600; font-size: var(--t-small);
}
.uprow {
  display: flex; align-items: center; gap: 12px; width: 100%;
  padding: 14px 16px; margin-bottom: 10px; text-align: left;
  background: var(--card, #fff); border: 1px solid var(--line-2, rgba(29,29,31,0.1));
  border-radius: 16px; cursor: pointer; font: inherit; color: inherit;
}
.uprow:hover { border-color: var(--accent); }
.uprow .upmain { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.uprow .upmain b { font-weight: 700; }
.uprow .upmain span { color: var(--ink-2, #6e6e73); font-size: var(--t-small); }
.uprow .upwith { margin-left: auto; color: var(--ink-2, #6e6e73); font-size: var(--t-small); white-space: nowrap; }
.uprow .go { margin-left: 8px; color: var(--ink-2, #6e6e73); }
.uprow .upwith + .go { margin-left: 8px; }
.bookrow { margin: 6px 0 22px; }
.bookbtn {
  display: inline-block; background: var(--accent); color: #fff; text-decoration: none;
  padding: 12px 22px; border-radius: 980px; font-weight: 600; font-size: var(--t-small);
}
.bookbtn:hover { filter: brightness(1.06); }
#lsPpl { display: flex; flex-direction: column; gap: 8px; margin-bottom: 10px; }
#lsGroup .baddrow { margin-top: 4px; }
.endlinks { display: flex; gap: 14px; justify-content: center; margin-top: 18px; flex-wrap: wrap; }
.endlinks a { color: var(--blue, #0071E3); text-decoration: none; font-weight: 600; font-size: 15px; }
.hw .backlink { display: inline-block; margin-bottom: 6px; color: var(--blue, #0071E3); text-decoration: none; font-weight: 600; font-size: var(--t-small); }
.qcard .sayit { display: block; width: 100%; text-align: center; color: var(--ink-2, #6e6e73); font-size: 12px; margin-top: 6px; }
