*{box-sizing:border-box;margin:0;padding:0;font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,Helvetica,Arial,sans-serif}
:root{
  /* Midnight Navy - premium dark, easy on eyes for long study sessions */
  --bg:#0B1220;--surface:#141C2F;--surface2:#1C2740;--surface3:#252F45;
  --border:#2B395A;--border2:#3D4F6E;
  /* Blue/red/purple are brightened from the stock 500-weight tints: on
     --surface3 (#252F45), the lightest dark panel and so the worst case for
     light text, the originals measured 3.63:1, 3.55:1 and 3.38:1 - under the
     4.5:1 AA floor. Green, orange and cyan already cleared it and are
     unchanged. Same hue and saturation, lightened only as far as needed. */
  --blue:#5D98F8;--blue-dim:rgba(59,130,246,.14);--blue-border:rgba(59,130,246,.40);
  --purple:#BC7CF9;--purple-dim:rgba(168,85,247,.14);--purple-border:rgba(168,85,247,.40);
  --green:#22c55e;--green-dim:rgba(34,197,94,.14);--green-border:rgba(34,197,94,.40);
  --red:#F36E6E;--red-dim:rgba(239,68,68,.14);--red-border:rgba(239,68,68,.40);
  --orange:#f59e0b;--orange-dim:rgba(245,158,11,.14);--orange-border:rgba(245,158,11,.40);
  --cyan:#06b6d4;--cyan-dim:rgba(6,182,212,.14);
  /* Eighth section accent. Seven cards had seven accents and the eighth
     (Entrance Test) had nowhere to go, so it borrowed Fundamentals' blue. */
  --teal:#2DD4BF;--teal-dim:rgba(45,212,191,.14);--teal-border:rgba(45,212,191,.40);
  --text:#F8FAFC;--text2:#CBD5E1;--text3:#94A3B8;
  --amber:#C8A44A;
  --amber-dim:rgba(200,164,74,.14);
  --amber-border:rgba(200,164,74,.40);
  /* Foreground for text sitting ON a filled accent chip (step-number
     circles, quiz option letters). Dark themes use bright accents, so the
     glyph must be dark; light theme uses darker accents, so it stays white.
     Hardcoded #fff was failing everywhere: 2.28:1 on green, 2.87 on blue. */
  --on-accent:#0B1220;
  --r4:6px;--r6:8px;--r8:12px;--r12:16px;
  --read-width:860px;
}
[data-theme="dark"]{
  --bg:#0B1220;--surface:#141C2F;--surface2:#1C2740;--surface3:#252F45;
  --border:#2B395A;--border2:#3D4F6E;
  --text:#F8FAFC;--text2:#CBD5E1;--text3:#94A3B8;
  --amber:#C8A44A;
  --amber-dim:rgba(200,164,74,.14);
  --amber-border:rgba(200,164,74,.40);
  --on-accent:#0B1220;
}
[data-theme="amoled"]{
  --bg:#000000;--surface:#0E0E0E;--surface2:#171717;--surface3:#1F1F1F;
  --border:#1F1F1F;--border2:#2D2D2D;
  --text:#FFFFFF;--text2:#E2E8F0;--text3:#94A3B8;
  --amber:#C8A44A;
  --amber-dim:rgba(200,164,74,.14);
  --amber-border:rgba(200,164,74,.40);
  --on-accent:#000000;
}
[data-theme="light"]{
  /* Accent + muted tones are DARKER here than in the dark themes, not merely
     recoloured. A hue that reads fine as light-on-dark fails badly as
     dark-on-light: measured against #FFFFFF, the previous values gave
     --text3 2.56:1, --orange 3.19:1, --green 3.30:1 and --cyan 3.68:1, all
     under the 4.5:1 WCAG AA floor for body text. --text3 in particular was
     copied verbatim from the dark palette (#94A3B8), so every caption,
     figure label and "Jump to section" hint was close to unreadable on
     white. Values below are the same hue and saturation, darkened only as
     far as needed. They are solved against --surface3 (#F1F5F9), the
     DARKEST light surface and therefore the worst case for dark text -
     solving against #FFFFFF alone leaves everything sitting on a tinted
     panel about 0.3 short. --purple is decorative only (no body text). */
  --bg:#F8FAFC;--surface:#FFFFFF;--surface2:#F8FAFC;--surface3:#F1F5F9;
  --border:#E2E8F0;--border2:#CBD5E1;
  --blue:#2563EB;--blue-dim:rgba(37,99,235,.06);--blue-border:rgba(37,99,235,.30);
  --purple:#7C3AED;--purple-dim:rgba(124,58,237,.10);--purple-border:rgba(124,58,237,.30);
  --green:#117F3A;--green-dim:rgba(22,163,74,.10);--green-border:rgba(22,163,74,.30);
  --red:#D52222;--red-dim:rgba(220,38,38,.10);--red-border:rgba(220,38,38,.30);
  --orange:#A25905;--orange-dim:rgba(217,119,6,.10);--orange-border:rgba(217,119,6,.30);
  --cyan:#06758F;--teal:#0F766E;--teal-dim:rgba(15,118,110,.12);--teal-border:rgba(15,118,110,.35);--cyan-dim:rgba(8,145,178,.10);
  --text:#0F172A;--text2:#475569;--text3:#5C708A;
  /* Same hue and saturation as the dark themes, darkened only as far as
     needed: #C8A44A measures 2.37:1 on white. Solved against --surface3
     (#F1F5F9), the darkest light surface and so the worst case. */
  --amber:#75601E;
  --amber-dim:rgba(117,96,30,.10);
  --amber-border:rgba(117,96,30,.32);
  --on-accent:#FFFFFF;
}
html{-webkit-text-size-adjust:100%}
body{background:var(--bg);color:var(--text);height:100vh;height:100dvh;display:flex;flex-direction:column;overflow:hidden;-webkit-font-smoothing:antialiased;font-size:16px;line-height:1.5}
/* Respect reduced-motion */
@media(prefers-reduced-motion:reduce){*{animation-duration:.01ms!important;transition-duration:.01ms!important}}
/* Accessible focus ring */
:focus-visible{outline:2px solid var(--blue);outline-offset:2px;border-radius:4px}

/* TOP BAR */
#topbar{display:flex;align-items:center;gap:12px;padding:0 20px;height:60px;background:var(--surface);border-bottom:1px solid var(--border);flex-shrink:0;position:sticky;top:0;z-index:50}
/* Guaranteed fallback for the profile/settings panel: backdrop-filter on #profile-modal
   establishes a containing block for its fixed children, which on some WebKit versions
   also disrupts paint order vs sticky siblings (#topbar) despite the z-index gap. Forcing
   #topbar below any open modal removes the ambiguity outright. */
html._modal-open #topbar{z-index:1}
#topbar .logo{display:flex;align-items:center;gap:0px;font-size:20px;font-weight:800;color:var(--text);letter-spacing:-.3px;white-space:nowrap;flex-shrink:0}
#topbar .logo .logo-mark{height:38px;width:auto;flex-shrink:0;display:block;margin-right:-2px}
#topbar .logo .logo-elec{color:var(--blue);font-size:inherit;font-weight:inherit;margin:0}
#topbar .logo .logo-sub{color:var(--text2);font-weight:500;font-size:12px;margin-left:8px}
.spacer{flex:1}

/* LAYOUT */
#layout{display:flex;flex:1;overflow:hidden;transition:filter .15s ease}
#layout._privacy-blur{filter:blur(22px) brightness(.7);pointer-events:none}

/* SIDEBAR (Desktop) / BOTTOM NAV (Mobile) */
#sidebar{width:232px;flex-shrink:0;background:var(--surface);border-right:1px solid var(--border);display:flex;flex-direction:column;overflow-y:auto;padding:10px 0}
.sb-section{padding:14px 16px 6px;font-size:10px;font-weight:700;color:var(--text3);text-transform:uppercase;letter-spacing:1.2px}
.sb-item{display:flex;align-items:center;gap:10px;padding:9px 14px;margin:1px 10px;border-radius:var(--r8);border:none;background:transparent;color:var(--text2);font-size:13.5px;font-weight:500;cursor:pointer;width:calc(100% - 20px);text-align:left;transition:background .15s,color .15s;min-height:44px}
.sb-item:hover{background:var(--surface2);color:var(--text)}
a.sb-item{text-decoration:none}
.sb-item.active{background:var(--blue-dim);color:var(--blue);font-weight:700}
.sb-item .ic{font-size:17px;width:22px;text-align:center;flex-shrink:0}
.sb-item .label{flex:1;line-height:1.3}
.sb-item .cnt{font-size:10px;padding:2px 7px;border-radius:10px;background:var(--surface3);color:var(--text3);font-weight:600;flex-shrink:0}
.sb-item.active .cnt{background:rgba(59,130,246,.18);color:var(--blue)}
.sb-divider{height:1px;background:var(--border);margin:8px 14px}

/* MAIN */
#main{flex:1;overflow:hidden;display:flex;flex-direction:column;background:var(--bg)}
#content{flex:1;overflow-y:auto;-webkit-overflow-scrolling:touch;padding:clamp(20px,3vw,36px) clamp(20px,4vw,48px);scroll-behavior:smooth}
#content::-webkit-scrollbar{width:5px}
#content::-webkit-scrollbar-thumb{background:var(--border2);border-radius:3px}
#content::-webkit-scrollbar-track{background:transparent}
.view{display:none}.view.active{display:block;animation:slideUp .22s ease}
@keyframes slideUp{from{opacity:0;transform:translateY(10px)}to{opacity:1;transform:translateY(0)}}
.content-spinner{display:flex;flex-direction:column;align-items:center;justify-content:center;gap:14px;padding:80px 20px;color:var(--text2);font-size:13.5px;animation:slideUp .2s ease}
.content-spinner .ring{width:34px;height:34px;border-radius:50%;border:3px solid var(--border2);border-top-color:var(--blue);animation:spin .7s linear infinite}
@keyframes spin{to{transform:rotate(360deg)}}

/* ═══ NOTES ═══ */
.note-doc{max-width:1050px;margin:0 auto}

/* Title card */
.note-title{padding:32px 28px 24px;background:linear-gradient(135deg,rgba(59,130,246,.10),rgba(168,85,247,.06));border:1px solid var(--border2);border-radius:var(--r12);margin-bottom:32px}
.note-title h1{font-size:26px;font-weight:800;color:var(--blue);margin-bottom:8px;letter-spacing:-.5px}
.note-title .sub{font-size:14px;color:var(--text2);line-height:1.6}
.note-title .tags{display:flex;flex-wrap:wrap;gap:8px;margin-top:16px}
.tag{padding:4px 12px;border-radius:20px;font-size:11.5px;font-weight:600;letter-spacing:.2px}
.tag-blue{background:var(--blue-dim);border:1px solid var(--blue-border);color:var(--blue)}
.tag-orange{background:var(--orange-dim);border:1px solid var(--orange-border);color:var(--orange)}
.tag-green{background:var(--green-dim);border:1px solid var(--green-border);color:var(--green)}
.tag-purple{background:var(--purple-dim);border:1px solid var(--purple-border);color:var(--purple)}

/* Section headings */
.n-h1{font-size:18px;font-weight:700;color:var(--blue);padding:12px 18px;margin:44px 0 16px;background:var(--blue-dim);border-radius:var(--r8);letter-spacing:-.1px;line-height:1.4}
.n-h2{font-size:15px;font-weight:700;color:color-mix(in srgb,var(--purple) 82%,var(--text));padding:9px 14px;margin:28px 0 12px;background:var(--purple-dim);border-radius:var(--r6);letter-spacing:-.1px;line-height:1.4}
.n-h3{font-size:13px;font-weight:700;color:var(--text2);margin:20px 0 8px;padding:0 2px;text-transform:uppercase;letter-spacing:.6px}

/* Body text */
.n-p{font-size:15.5px;line-height:1.78;color:var(--text);margin:14px 0}
.n-val{display:inline;padding:2px 8px;border-radius:4px;background:var(--orange-dim);border:1px solid var(--orange-border);color:var(--orange);font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;font-size:13.5px;font-weight:600;white-space:nowrap;max-width:100%;overflow-wrap:anywhere}

/* Callout boxes - important info, not alarming */
.n-crit,.n-warn,.n-info,.n-ok{display:flex;gap:14px;align-items:flex-start;border-radius:var(--r8);padding:16px 18px;margin:20px 0;border:1px solid}
.n-crit{background:linear-gradient(135deg,rgba(239,68,68,.18),rgba(239,68,68,.07));border-color:rgba(239,68,68,.30)}
.n-crit .icon{font-size:20px;color:var(--red);flex-shrink:0;margin-top:2px}
.eb-stars{display:inline-flex;gap:1px;vertical-align:-2px;color:var(--orange);font-size:.95em;white-space:nowrap}
.eb-stars .svg-ic{fill:currentColor;stroke:none}
.eb-tag-ic{display:inline-flex;vertical-align:-2px;margin-right:5px}
.n-crit .body{font-size:15px;color:var(--text);line-height:1.75}
.n-warn{background:linear-gradient(135deg,rgba(245,158,11,.16),rgba(245,158,11,.06));border-color:rgba(245,158,11,.30)}
.n-warn .icon{font-size:20px;color:var(--orange);flex-shrink:0;margin-top:2px}
.n-warn .body{font-size:15px;color:var(--text);line-height:1.75}
.n-info{background:linear-gradient(135deg,rgba(59,130,246,.16),rgba(59,130,246,.06));border-color:rgba(59,130,246,.30)}
.n-info .icon{font-size:20px;color:var(--blue);flex-shrink:0;margin-top:2px}
.n-info .body{font-size:15px;color:var(--text);line-height:1.75}
.n-ok{background:linear-gradient(135deg,rgba(34,197,94,.16),rgba(34,197,94,.06));border-color:rgba(34,197,94,.30)}
.n-ok .icon{font-size:20px;color:var(--green);flex-shrink:0;margin-top:2px}
.n-ok .body{font-size:15px;color:var(--text);line-height:1.75}
.n-crit .body strong{color:var(--red);font-weight:700}
.n-warn .body strong{color:var(--orange);font-weight:700}

/* A callout class combined with .n-card is a TINTED CARD, not a callout.

   .n-crit/.n-warn/.n-info/.n-ok are display:flex because a callout is an icon
   beside a body. Writing class="n-card n-info" to get a tinted card inherits
   that flex, and every block inside then becomes a flex item laid out in a
   row: on T13 a nested .n-warn landed 179px wide at x=468 inside a 502px card
   and hung 79px past the page, which made #content horizontally scrollable
   (it sets overflow-y:auto and leaves overflow-x unset, and CSS resolves the
   unset axis to auto). Only visible between 769px and ~900px, because below
   769px .note-doc clips horizontally and above ~900px there is room to spare.

   All six instances in the content hold block content and none uses the
   icon/body structure, so restoring block display is the correct shape and
   keeps the tint and border the author wanted. */
.n-card.n-crit, .n-card.n-warn, .n-card.n-info, .n-card.n-ok { display: block; }

/* A grid item's automatic minimum size is its min-content size, which is why a
   wide table drags its whole track open even when the track is meant to be
   1fr. min-width:0 opts out of that, so the cell takes the width it is given
   and the table scrolls inside its own .n-table-wrap instead. Applied to the
   children rather than only the track definition because several oral topics
   set grid-template-columns inline, where a track-level fix cannot reach. */
.n-grid > *, .n-grid-3 > *, .note-doc [style*="grid-template-columns"] > * { min-width: 0; }

/* Same rule, flex instead of grid. .n-crit/.n-warn/.n-info/.n-ok are flex rows
   (icon beside body), and .body is a flex item, so its automatic minimum size
   is its min-content width: a wide table or a long unbreakable value inside a
   callout drags the whole callout past the page. T22 did exactly that on every
   phone in portrait, 165-248px past the edge depending on the handset, hidden
   by .note-doc's clipping and reachable only by a stray sideways scroll.
   The icon keeps flex-shrink:0 so it never squashes. */
.n-crit > .body, .n-warn > .body, .n-info > .body, .n-ok > .body { min-width: 0; }
.n-info .body strong{color:color-mix(in srgb,var(--blue) 80%,var(--text));font-weight:700}
.n-ok .body strong{color:var(--green);font-weight:700}
[data-theme="light"] .n-crit,[data-theme="light"] .n-warn,[data-theme="light"] .n-info,[data-theme="light"] .n-ok{box-shadow:none}

/* Lists - clean, scannable */
.n-list{margin:12px 0;list-style:none;padding:0}
.n-list li{padding:5px 0 5px 24px;font-size:15px;line-height:1.7;color:var(--text);position:relative}
.n-list li::before{content:'\25B8';color:var(--blue);font-size:14px;position:absolute;left:4px;top:6px;line-height:1}
.n-list li strong{color:var(--text);font-weight:600}
.n-list li em{color:var(--orange);font-style:normal;font-weight:600}

/* Cards & Grid */
/* minmax(0,1fr), not 1fr. A grid item defaults to min-width:auto, so a cell
   whose content has a wide min-content size - a .n-table with three columns
   is the usual one - pushes its track wider than the track is allowed to be,
   and the whole grid then overhangs the page. Found on W07 at 820px, where a
   Hyper Mist comparison table made a card 400px wide in a 383px track and hung
   17px past the edge. Below 768px the grids collapse to one column so it never
   showed on a phone, and above ~900px there is room to spare, which left the
   tablet widths in between as the only place it was visible.
   With the track free to shrink, the table scrolls inside its own
   .n-table-wrap instead of moving the layout. */
.n-grid{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:14px;margin:14px 0}
.n-grid-3{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:14px;margin:14px 0}
.n-card{background:var(--surface2);border:1px solid var(--border2);border-radius:var(--r12);padding:18px;transition:border-color .2s,transform .2s,box-shadow .2s}
.n-card:hover{transform:translateY(-3px);border-color:var(--border2);box-shadow:0 10px 24px rgba(0,0,0,.2)}
.n-card .card-title{font-size:11px;font-weight:700;color:var(--text3);text-transform:uppercase;letter-spacing:.8px;margin-bottom:10px}
.n-card .card-val{font-size:24px;font-weight:800;color:var(--blue);margin-bottom:6px}
.n-card .card-desc{font-size:13.5px;color:var(--text2);line-height:1.6}

/* Table - clean academic style */
.n-table{width:100%;border-collapse:separate;border-spacing:0;margin:20px 0;font-size:14px;border:1px solid var(--border2);border-radius:var(--r12);overflow:hidden;box-shadow:0 2px 12px rgba(0,0,0,.15)}
.n-table th{background:var(--surface3);padding:11px 14px;text-align:left;font-size:11px;font-weight:700;color:var(--text2);text-transform:uppercase;letter-spacing:.6px;border-bottom:1px solid var(--border2);position:sticky;top:0}
.n-table td{padding:12px 14px;border-bottom:1px solid var(--border);color:var(--text);line-height:1.6}
.n-table tbody tr:nth-child(even) td{background:rgba(255,255,255,.025)}
[data-theme="light"] .n-table tbody tr:nth-child(even) td{background:rgba(0,0,0,.03)}
.n-table tr:last-child td{border-bottom:none}
.n-table tr:hover td{background:var(--surface3)!important}
.n-table .hl{color:var(--orange);font-weight:700}
.n-table .ok{color:var(--green);font-weight:700}
.n-table .bad{color:var(--red);font-weight:700}

/* Scroll hint: a table that overflows on mobile (see the max-width:768px
   rule below) reads as clean and complete, not cut off - nothing about it
   suggests there is more to the right. app.js wraps any table that actually
   overflows (measured, not guessed from viewport width) with .n-table-wrap
   and adds this badge, which fades out the first time that table is
   scrolled or touched. Reuses --on-accent, added earlier for exactly this
   "glyph on a filled accent circle" case. */
.n-table-wrap{position:relative;overflow-x:auto;-webkit-overflow-scrolling:touch}
.n-table-hint{
  display:none;position:absolute;top:50%;right:8px;transform:translateY(-50%);
  width:26px;height:26px;border-radius:50%;
  background:var(--blue);color:var(--on-accent);
  align-items:center;justify-content:center;font-size:13px;
  box-shadow:0 2px 10px rgba(0,0,0,.35);
  pointer-events:none;transition:opacity .35s ease;
  animation:nTableHintPulse 1.6s ease-in-out infinite;
}
.n-table-wrap.has-scroll-hint .n-table-hint{display:flex}
.n-table-wrap.hint-dismissed .n-table-hint{opacity:0}
@keyframes nTableHintPulse{0%,100%{opacity:.55}50%{opacity:1}}
@media(prefers-reduced-motion:reduce){.n-table-hint{animation:none}}

/* Formula - monospace focus box */
.n-formula{background:var(--surface3);border:1px solid rgba(6,182,212,.30);border-left:4px solid rgba(6,182,212,.85);border-radius:var(--r8);padding:22px 24px;margin:20px 0;font-family:ui-monospace,SFMono-Regular,monospace;font-size:19px;color:var(--text);text-align:center;box-shadow:0 2px 20px rgba(6,182,212,.10)}
.n-formula .label{font-family:-apple-system,sans-serif;font-size:12px;color:var(--text3);margin-top:10px;letter-spacing:.3px}
[data-theme="dark"] .n-formula, [data-theme="amoled"] .n-formula { color: #FF9F0A; }
[data-theme="light"] .n-formula{box-shadow:none}

/* Steps - numbered procedure */
.n-steps{margin:12px 0;counter-reset:step;list-style:none;padding:0}
.n-steps ol, .n-steps ul{list-style:none;padding:0;margin:0}
.n-steps li{padding:7px 0 7px 38px;font-size:15px;line-height:1.7;color:var(--text);counter-increment:step;position:relative}
.n-steps li::before{content:counter(step);background:var(--blue);color:var(--on-accent);font-size:11px;font-weight:800;width:22px;height:22px;border-radius:50%;display:inline-flex;align-items:center;justify-content:center;position:absolute;left:0;top:9px}
.n-steps li strong{color:var(--text);font-weight:600}
.n-steps li .n-formula{margin-left:-38px}

/* Numericals detail header - title + Prev/Next */
.num-detail-head{display:flex;justify-content:space-between;align-items:flex-start;gap:16px}
.num-detail-nav{display:flex;gap:8px;flex-shrink:0}
@media(max-width:768px){
  .num-detail-head{flex-direction:column;gap:12px}
  .num-detail-nav{width:100%;justify-content:space-between}
}

/* Section jump anchors */
.note-anchors{display:flex;flex-wrap:wrap;gap:7px;padding:14px 16px;margin-bottom:20px;background:var(--surface2);border:1px solid var(--border);border-radius:var(--r12)}
.note-anchors span{font-size:12px;color:var(--text3);font-weight:700;text-transform:uppercase;letter-spacing:.8px;width:100%;margin-bottom:4px}
.anc-btn{display:inline-flex;align-items:center;justify-content:center;min-height:44px;padding:5px 13px;border-radius:20px;border:1px solid var(--border2);background:var(--surface3);color:var(--text2);font-size:12.5px;font-weight:600;cursor:pointer;transition:border-color .2s,color .2s,background .2s}
.anc-btn:hover{border-color:var(--blue);color:var(--blue);background:var(--blue-dim)}
.anc-btn:active{transform:scale(0.95)}

/* ═══ QUIZ ═══ */
#quiz-home{max-width:900px}
.quiz-topic-header{padding:24px;margin-bottom:24px;background:linear-gradient(135deg,rgba(34,197,94,.1),rgba(59,130,246,.08));border:1px solid var(--green-border);border-radius:var(--r12);display:flex;align-items:center;gap:20px;box-shadow:0 4px 16px rgba(0,0,0,.15)}
.quiz-topic-header .icon{font-size:36px;transition:transform .2s cubic-bezier(0.16,1,0.3,1)}
.quiz-topic-header:hover .icon{transform:scale(1.15) rotate(-5deg)}
.quiz-topic-header h2{font-size:22px;font-weight:800;color:var(--green);letter-spacing:-.5px}
.quiz-topic-header p{font-size:14px;color:var(--text2);margin-top:4px}
.quiz-topic-header .total{margin-left:auto;text-align:center;flex-shrink:0}
.quiz-topic-header .total .num{font-size:36px;font-weight:800;color:var(--green)}
.quiz-topic-header .total .lbl{font-size:12px;color:var(--text3);text-transform:uppercase;letter-spacing:.5px;margin-top:2px}
.qcat-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(220px,1fr));gap:12px;margin-bottom:20px}
.qcat-btn{display:flex;flex-direction:column;gap:6px;padding:16px 20px;background:var(--surface2);border:1px solid var(--border);border-radius:var(--r12);cursor:pointer;text-align:left;transition:background .2s,border-color .2s,color .2s,transform .2s,opacity .2s;min-height:80px;box-shadow:0 2px 6px rgba(0,0,0,.1)}
.qcat-btn:hover{border-color:var(--blue);background:var(--surface3);transform:translateY(-4px) scale(1.02);box-shadow:0 12px 24px rgba(0,0,0,.25)}
.qcat-btn:active{transform:translateY(0) scale(0.96)}
.qcat-btn.all-btn{border-color:var(--green-border);background:var(--green-dim)}
.qcat-btn.all-btn:hover{border-color:var(--green);background:rgba(34,197,94,.2)}
.qcat-btn .cat-name{font-size:14px;font-weight:700;color:var(--text)}
.qcat-btn.all-btn .cat-name{color:var(--green)}
.qcat-btn .cat-count{font-size:12px;color:var(--text3);margin-top:auto}
.qcat-btn.all-btn .cat-count{color:rgba(34,197,94,.8)}
.qcat-btn .cat-bar{height:4px;background:var(--border);border-radius:2px;margin-top:8px;overflow:hidden}
.qcat-btn .cat-fill{height:100%;background:var(--blue);border-radius:2px;transition:width .4s cubic-bezier(0.16,1,0.3,1)}
.qcat-btn.all-btn .cat-fill{background:var(--green)}

/* Quiz active */
#quiz-active{display:none;max-width:720px;margin:0 auto}
.quiz-progress{margin-bottom:24px}
.quiz-progress-top{display:flex;justify-content:space-between;align-items:center;margin-bottom:10px}
.quiz-progress-top .qnum{font-size:14px;font-weight:600;color:var(--text2)}
.quiz-progress-top .score{font-size:14px;font-weight:800;color:var(--green)}
.quiz-progress-top .cat-tag{font-size:12px;padding:4px 10px;border-radius:12px;background:var(--blue-dim);border:1px solid var(--blue-border);color:var(--blue);font-weight:600}
.qbar{height:6px;background:var(--surface3);border-radius:3px;overflow:hidden}
.qfill{height:100%;background:linear-gradient(90deg,var(--blue),var(--purple));border-radius:3px;transition:width .3s cubic-bezier(0.16,1,0.3,1)}
/* Quiz card - clean study mode, distraction-free */
.quiz-card{background:var(--surface);border:1px solid var(--border2);border-radius:var(--r12);overflow:hidden;box-shadow:0 4px 20px rgba(0,0,0,.2)}
.quiz-q-area{padding:28px 24px 18px}
.quiz-q-area .qtext{font-size:17px;font-weight:600;line-height:1.7;color:var(--text)}
.quiz-opts{display:flex;flex-direction:column;gap:10px;padding:14px 24px 20px}
.qopt{display:flex;align-items:center;gap:14px;padding:14px 18px;background:var(--surface2);border:1px solid var(--border);border-radius:var(--r12);cursor:pointer;text-align:left;width:100%;transition:border-color .15s,background .15s;min-height:56px}
.qopt:hover:not(:disabled){background:var(--surface3);border-color:var(--border2)}
.qopt:active:not(:disabled){transform:scale(0.98)}
.qopt .opt-letter{width:28px;height:28px;border-radius:50%;background:var(--surface3);border:1px solid var(--border2);font-size:12px;font-weight:800;color:var(--text2);display:flex;align-items:center;justify-content:center;flex-shrink:0}
.qopt .opt-text{font-size:14.5px;color:var(--text);line-height:1.6;flex:1;text-align:left;font-weight:500}
.qopt.correct{background:rgba(34,197,94,.08)!important;border-color:rgba(34,197,94,.4)!important}
.qopt.correct .opt-letter{background:var(--green);border-color:var(--green);color:var(--on-accent)}
.qopt.correct .opt-text{color:#a7f3c0!important;font-weight:600}
.qopt.wrong{background:rgba(239,68,68,.08)!important;border-color:rgba(239,68,68,.4)!important;animation:shake 0.4s cubic-bezier(0.36,0.07,0.19,0.97) both}
@keyframes shake{10%,90%{transform:translate3d(-2px,0,0)}20%,80%{transform:translate3d(4px,0,0)}30%,50%,70%{transform:translate3d(-6px,0,0)}40%,60%{transform:translate3d(6px,0,0)}}
.qopt.wrong .opt-letter{background:var(--red);border-color:var(--red);color:var(--on-accent)}
.qopt.wrong .opt-text{color:#fca5a5!important}
.qopt:disabled{cursor:default}
/* Explanation box - the key study element */
.quiz-exp{margin:0 24px 16px;padding:14px 18px;background:rgba(59,130,246,.07);border:1px solid rgba(59,130,246,.2);border-radius:var(--r8);font-size:13.5px;color:#c4d9fe;line-height:1.75;display:none}
.quiz-exp.show{display:block}
.quiz-exp strong{color:#fff;font-weight:700}
.quiz-actions{display:flex;align-items:center;justify-content:space-between;padding:14px 22px;background:var(--surface2);border-top:1px solid var(--border)}
.quiz-actions .hint{font-size:13px;color:var(--text3);font-weight:500;transition:opacity 0.3s}
.btn{display:inline-flex;align-items:center;justify-content:center;min-height:44px;padding:0 24px;border-radius:var(--r8);border:none;font-size:14px;font-weight:700;cursor:pointer;transition:background .15s,border-color .15s,color .15s,transform .15s;box-shadow:0 2px 4px rgba(0,0,0,.2)}
.btn:active{transform:scale(0.95)}
.btn-primary{background:var(--blue);color:var(--on-accent)}
.btn-primary:hover{filter:brightness(.92);box-shadow:0 6px 16px rgba(59,130,246,.4);transform:translateY(-2px)}
.btn-ghost{background:var(--surface3);border:1px solid var(--border2);color:var(--text2);box-shadow:none}
.btn-ghost:hover{background:var(--surface2);color:var(--text);transform:translateY(-2px)}
.btn-green{background:var(--green);color:var(--on-accent)}
/* Darkened with a filter rather than a fixed hex. The old hover pinned
   #16a34a while the label stayed themed, which is the paired-colour bug:
   it measured 3.29:1 against white in the light theme. */
.btn-green:hover{filter:brightness(.92);box-shadow:0 6px 16px rgba(34,197,94,.4);transform:translateY(-2px)}
.score-screen{text-align:center;padding:48px 32px;background:var(--surface);border:1px solid var(--border2);border-radius:var(--r12);max-width:460px;margin:0 auto;box-shadow:0 8px 30px rgba(0,0,0,.3)}
.score-emoji{font-size:64px;margin-bottom:20px;}
.score-pct{font-size:56px;font-weight:800;margin-bottom:8px;color:var(--blue);letter-spacing:-1px;}
.score-sub{font-size:15px;color:var(--text2);margin-bottom:32px;line-height:1.5;}
.score-breakdown{display:grid;grid-template-columns:1fr 1fr 1fr;gap:12px;margin-bottom:32px;}
.score-stat{background:var(--surface2);border:1px solid var(--border);border-radius:var(--r8);padding:16px 12px;transition:transform 0.3s cubic-bezier(0.16,1,0.3,1)}
.score-stat:hover{transform:translateY(-4px) scale(1.05)}
.score-stat .n{font-size:28px;font-weight:800;color:var(--text)}
.score-stat .l{font-size:12px;color:var(--text3);margin-top:4px;text-transform:uppercase;letter-spacing:.5px;font-weight:600}
.score-actions{display:flex;gap:12px;justify-content:center;flex-wrap:wrap;}

/* Welcome */
/* 960, not 800. Three cards fit either way, but at 800 each one is 253px
   and the copy runs to six cramped lines. The heading and lead paragraph
   keep their own narrower measure below so the page does not turn into a
   wide banner. */
.welcome{max-width:960px;margin:0 auto;text-align:center;padding-top:48px}
.welcome h1,.welcome>p{max-width:760px;margin-left:auto;margin-right:auto}
.welcome h1{font-size:36px;font-weight:800;color:var(--text);margin-bottom:12px;letter-spacing:-1px}
.welcome h1 span{color:var(--blue)}
.welcome p{font-size:16px;color:var(--text2);line-height:1.6;max-width:540px;margin:0 auto 40px}
/* auto-fit, not a fixed 1fr 1fr. The home grid was two columns forever, so
   a third card wrapped onto its own row and looked like an afterthought.
   Now it fits what is there: three across on a desktop, two on a narrow
   window, one on a phone via the 768px rule below. */
.welcome-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(240px,1fr));gap:20px;text-align:left}
.welcome-card{padding:24px;background:var(--surface);border:1px solid var(--border);border-radius:var(--r12);cursor:pointer;transition:background .2s,border-color .2s,color .2s,transform .2s,opacity .2s;box-shadow:0 4px 12px rgba(0,0,0,.1)}
.welcome-card:hover{border-color:var(--blue);transform:translateY(-4px);box-shadow:0 14px 30px rgba(0,0,0,.18)}
.welcome-card .wc-icon{font-size:32px;margin-bottom:16px;transition:background .2s,border-color .2s,color .2s,transform .2s,opacity .2s}
.welcome-card:hover .wc-icon{transform:translateY(-6px);filter:drop-shadow(0 8px 12px rgba(59,130,246,0.6))}
.welcome-card h2,.welcome-card h3{font-size:18px;font-weight:700;color:var(--text);margin-bottom:8px}
.welcome-card p{font-size:14px;color:var(--text2);line-height:1.6}
.welcome-card .wc-badge{display:inline-block;margin-top:16px;padding:4px 12px;border-radius:20px;font-size:12px;font-weight:700;background:var(--blue-dim);border:1px solid var(--blue-border);color:var(--blue)}

/* ─── MOBILE TOPIC STRIP (shows above notes on mobile only) ─── */
.mobile-topic-strip{display:none;overflow-x:auto;white-space:nowrap;padding:0 0 12px;margin-bottom:8px;scrollbar-width:none}
.mobile-topic-strip::-webkit-scrollbar{display:none}
.mts-btn{display:inline-flex;align-items:center;gap:5px;padding:10px 12px;min-height:44px;border-radius:20px;border:1px solid var(--border2);background:var(--surface2);color:var(--text3);font-size:11px;font-weight:600;cursor:pointer;white-space:nowrap;transition:background .2s,border-color .2s,color .2s,transform .2s;opacity:0.5;margin-right:6px}
.mts-btn:hover{opacity:0.85;border-color:var(--border)}
.mts-btn.mts-active{opacity:1;background:var(--blue-dim);border-color:var(--blue);color:var(--blue)}
@media(max-width:768px){.mobile-topic-strip{display:block}.topic-footer-nav{flex-wrap:wrap;gap:8px}.tfn-btn{max-width:100%;flex:1 1 calc(50% - 14px)}.tfn-center{width:100%;order:3;padding-top:4px}}

/* ─── TOPIC SIDEBAR LIST ─── */
#topic-side-list{display:none;overflow-y:auto;flex:1;padding:4px 0 16px;border-top:1px solid var(--border);margin-top:4px;min-height:0}
.tl-item{display:flex;align-items:center;gap:8px;padding:6px 10px;min-height:44px;margin:1px 6px;border-radius:var(--r8);border:none;background:transparent;cursor:pointer;width:calc(100% - 12px);text-align:left;transition:background .15s,border-color .15s,color .15s;opacity:0.35;font-size:12px;color:var(--text2);line-height:1.3;position:relative}
.tl-prog-wrap{position:absolute;bottom:0;left:10px;right:10px;height:2px;background:var(--surface3);border-radius:1px;overflow:hidden}
.tl-prog{height:100%;background:var(--blue);border-radius:1px;transition:width .5s ease}
.tl-item:hover{opacity:0.75;background:var(--surface2);color:var(--text)}
.tl-item.tl-active{opacity:1;background:var(--blue-dim);color:var(--blue);font-weight:700}
.tl-item .tl-ic{font-size:13px;width:17px;flex-shrink:0}
.tl-item .tl-ic:empty{display:none}
.tl-item .tl-label{flex:1;font-size:11.5px}
.tl-item .tl-num{font-size:9px;font-weight:800;opacity:0.5;flex-shrink:0;font-family:monospace}
.tl-item.tl-active .tl-num{opacity:0.7;color:var(--blue)}


.tin-arrow{display:flex;align-items:center;justify-content:center;width:34px;height:34px;border-radius:var(--r8);border:1px solid var(--border2);background:var(--surface2);color:var(--text2);font-size:14px;cursor:pointer;transition:background .15s,border-color .15s,color .15s;flex-shrink:0;text-decoration:none}
.tin-arrow:hover{border-color:var(--blue);color:var(--blue);background:var(--blue-dim)}
.tin-arrow.disabled{opacity:0.3;cursor:not-allowed;pointer-events:none}
.tin-pill{flex:1;display:flex;align-items:center;justify-content:center;gap:7px;height:34px;border-radius:var(--r8);border:1px solid var(--border2);background:var(--surface2);color:var(--text2);font-size:12.5px;font-weight:600;cursor:pointer;transition:background .15s,border-color .15s,color .15s;user-select:none}
.tin-pill:hover{border-color:var(--blue);color:var(--blue);background:var(--blue-dim)}
.tin-pill.open{border-color:var(--blue);color:var(--blue);background:var(--blue-dim);border-bottom-left-radius:0;border-bottom-right-radius:0}
.tin-pill .tin-ic{font-size:15px}
.tin-pill .tin-arrow-icon{font-size:9px;opacity:.6;transition:transform .2s}
.tin-pill.open .tin-arrow-icon{transform:rotate(180deg)}
.tin-inner{position:relative}
.tin-dropdown{display:none;position:absolute;top:100%;left:42px;right:42px;background:var(--surface2);border:1px solid var(--blue);border-top:none;border-bottom-left-radius:var(--r8);border-bottom-right-radius:var(--r8);z-index:200;max-height:320px;overflow-y:auto;box-shadow:0 8px 24px rgba(0,0,0,.3)}
.tin-dropdown.open{display:block}
.tin-dropdown::-webkit-scrollbar{width:4px}
.tin-dropdown::-webkit-scrollbar-thumb{background:var(--border2);border-radius:2px}
.tin-drop-item{display:flex;align-items:center;gap:10px;padding:8px 14px;cursor:pointer;font-size:12.5px;color:var(--text2);transition:background .1s}
.tin-drop-item:hover{background:var(--surface3);color:var(--text)}
.tin-drop-item.tin-active{background:var(--blue-dim);color:var(--blue);font-weight:700}
.tin-drop-item .tin-num{font-size:10px;font-family:monospace;opacity:0.5;margin-left:auto;flex-shrink:0}
.tin-drop-item.tin-active .tin-num{opacity:0.7}

/* ─── QUIZ BANK ─── */
#view-quiz-bank{max-width:720px}
.qb-header{margin-bottom:28px}
.qb-header h2{font-size:20px;font-weight:800;color:var(--text);letter-spacing:-.3px;margin-bottom:6px}
.qb-header p{font-size:13.5px;color:var(--text2)}
.qb-row{margin-bottom:22px}
.qb-label{font-size:11px;font-weight:800;color:var(--text3);text-transform:uppercase;letter-spacing:1px;margin-bottom:10px}
/* Section toggle */
.qb-seg{display:flex;gap:0;border:1px solid var(--border2);border-radius:var(--r8);overflow:hidden;width:fit-content}
.qb-seg-btn{padding:9px 24px;min-height:44px;border:none;background:var(--surface2);color:var(--text2);font-size:13px;font-weight:600;cursor:pointer;transition:background .15s,border-color .15s,color .15s;border-right:1px solid var(--border2)}
.qb-seg-btn:last-child{border-right:none}
.qb-seg-btn:hover:not(.disabled){background:var(--surface3);color:var(--text)}
.qb-seg-btn.active{background:var(--blue);color:var(--on-accent)}
.qb-seg-btn.disabled{opacity:0.35;cursor:not-allowed}
/* Topic dropdown */
.qb-dropdown{position:relative}
.qb-dropdown-trigger{display:flex;align-items:center;justify-content:space-between;gap:10px;padding:10px 16px;background:var(--surface2);border:1px solid var(--border2);border-radius:var(--r8);cursor:pointer;transition:border-color .15s;min-width:min(280px,100%);font-size:13.5px;color:var(--text)}
.qb-dropdown-trigger:hover{border-color:var(--blue)}
.qb-dropdown-trigger.open{border-color:var(--blue);border-bottom-color:transparent;border-radius:var(--r8) var(--r8) 0 0}
.qb-dropdown-trigger .arrow{font-size:10px;color:var(--text3);transition:transform .2s}
.qb-dropdown-trigger.open .arrow{transform:rotate(180deg)}
.qb-dropdown-panel{display:none;position:absolute;top:100%;left:0;right:0;background:var(--surface2);border:1px solid var(--blue);border-top:none;border-radius:0 0 var(--r8) var(--r8);z-index:200;max-height:200px;overflow-y:auto;box-shadow:0 8px 24px rgba(0,0,0,.3)}
.qb-dropdown-panel.open{display:block}
.qb-dropdown-panel::-webkit-scrollbar{width:4px}
.qb-dropdown-panel::-webkit-scrollbar-thumb{background:var(--border2);border-radius:2px}
.qb-drop-item{display:flex;align-items:center;gap:10px;padding:9px 14px;cursor:pointer;transition:background .1s;font-size:13px;color:var(--text2)}
.qb-drop-item:hover{background:var(--surface3);color:var(--text)}
.qb-drop-item.checked{color:var(--blue)}
.qb-drop-item .chk{width:14px;height:14px;border-radius:3px;border:1.5px solid var(--border2);flex-shrink:0;display:flex;align-items:center;justify-content:center;font-size:10px;transition:background .15s,border-color .15s,color .15s}
.qb-drop-item.checked .chk{background:var(--blue);border-color:var(--blue);color:var(--on-accent)}
.qb-drop-divider{height:1px;background:var(--border);margin:4px 0}
.qb-drop-all{font-weight:700;color:var(--text)}
/* Category pills - full names */
.qb-cats{display:flex;flex-wrap:wrap;gap:7px}
.qb-cat-pill{padding:6px 14px;border-radius:20px;border:1px solid var(--border2);background:var(--surface2);color:var(--text2);font-size:12.5px;font-weight:500;cursor:pointer;transition:background .15s,border-color .15s,color .15s;white-space:nowrap}
.qb-cat-pill:hover{border-color:var(--border2);color:var(--text);background:var(--surface3)}
.qb-cat-pill.active{background:var(--blue-dim);border-color:var(--blue-border);color:var(--blue);font-weight:700}
.qb-cat-pill.all-cat.active{background:var(--green-dim);border-color:var(--green-border);color:var(--green)}
.qb-cats-empty{font-size:13px;color:var(--text3);padding:4px 0}
/* Count */
.qb-count-row{display:flex;gap:8px;flex-wrap:wrap}
.qb-cnt-btn{padding:8px 20px;border-radius:var(--r8);border:1px solid var(--border2);background:var(--surface2);color:var(--text2);font-size:13px;font-weight:700;cursor:pointer;transition:background .15s,border-color .15s,color .15s;min-height:44px}
.qb-cnt-btn:hover{color:var(--text);background:var(--surface3)}
.qb-cnt-btn.active{background:var(--purple-dim);border-color:var(--purple-b);color:var(--purple)}
/* Footer */
.qb-footer{display:flex;align-items:center;gap:16px;margin-top:28px;padding-top:20px;border-top:1px solid var(--border)}
.qb-preview{font-size:13px;color:var(--text2);flex:1;line-height:1.6}
.qb-preview strong{color:var(--text);font-weight:700}
.qb-start{padding:0 32px;height:46px;background:var(--blue);color:var(--on-accent);border:none;border-radius:var(--r8);font-size:14px;font-weight:700;cursor:pointer;transition:background .2s,transform .2s;white-space:nowrap}
.qb-start:hover{filter:brightness(.92);transform:translateY(-2px);box-shadow:0 6px 16px rgba(59,130,246,.35)}
.qb-start:disabled{opacity:.35;cursor:not-allowed;transform:none;box-shadow:none}

/* ─── BOTTOM TOPIC FOOTER NAV ─── */
.topic-footer-nav{display:flex;align-items:stretch;gap:10px;margin-top:48px;padding:20px 0 8px;border-top:1px solid var(--border)}
.tfn-btn{flex:1;display:flex;flex-direction:column;gap:3px;padding:14px 18px;background:var(--surface2);border:1px solid var(--border2);border-radius:var(--r12);cursor:pointer;transition:background .15s,border-color .15s,color .15s,transform .15s;max-width:calc(50% - 22px);text-align:left}
.tfn-btn:hover{border-color:var(--blue);transform:translateY(-2px);box-shadow:0 8px 20px rgba(0,0,0,.2)}
.tfn-btn.tfn-next{text-align:right;margin-left:auto}
.tfn-btn.disabled{opacity:0.2;cursor:not-allowed;pointer-events:none}
.tfn-btn.disabled:hover{transform:none;box-shadow:none}
.tfn-dir{font-size:10px;color:var(--text3);font-weight:700;text-transform:uppercase;letter-spacing:.5px}
.tfn-name{font-size:12.5px;color:var(--text);font-weight:600;line-height:1.4;margin-top:3px}
.tfn-center{display:flex;align-items:center;justify-content:center;font-size:11px;color:var(--text3);padding:0 4px;flex-shrink:0}


/* Hamburger Menu Defaults */
#mobile-menu-btn {
  display: none;
  align-items: center;
  justify-content: center;
  background: transparent;
  border: none;
  color: var(--text);
  padding: 6px;
  margin-right: 12px;
  margin-left: -4px;
  cursor: pointer;
  border-radius: var(--r8);
  transition: background 0.2s;
}
#mobile-menu-btn:hover { background: rgba(255,255,255,0.05); }
#sidebar-overlay { display: none; }

.mobile-sidebar-header { display: none; }

/* MOBILE RESPONSIVE OVERRIDES */
@media (max-width: 768px) {
  html, body {
    overflow-x: hidden !important;
    max-width: 100vw;
  }

  #mobile-menu-btn { display: inline-flex; }
  
  /* Slide-out Sidebar Morph */
  .mobile-sidebar-header {
    display: flex;
    align-items: center;
    padding: 16px 20px;
    border-bottom: 1px solid var(--border);
    margin-bottom: 8px;
    background: var(--surface);
  }
  
  #sidebar {
    will-change: transform;
    position: fixed;
    top: 0; /* Cover topbar */
    left: 0;
    bottom: 0;
    width: 280px;
    height: 100svh;
    z-index: 2000;
    transform: translateX(-300px);
    transition: transform 0.3s cubic-bezier(0.16, 1, 0.3, 1);
    box-shadow: none;
  }
  #sidebar.open {
    transform: translateX(0);
    box-shadow: 4px 0 24px rgba(0,0,0,0.5);
  }
  
  #sidebar-overlay {
    display: block;
    position: fixed;
    top: 0;
    left: 0;
    right: 0;
    bottom: 0;
    background: rgba(0,0,0,0.6);
    
    z-index: 1999;
    opacity: 0;
    pointer-events: none;
    transition: opacity 0.3s ease;
  }
  #sidebar-overlay.open {
    opacity: 1;
    pointer-events: auto;
  }
  
  #layout, #main {
    overflow-x: hidden !important;
    max-width: 100vw;
  }
  #content {
    padding: 16px;
    overflow-x: hidden !important;
    max-width: 100%;
    -webkit-overflow-scrolling: touch;
  }
  
  /* Topbar */
  #topbar { padding: 0 16px; height: 56px; }
  
  /* Grids to 1 column - !important overrides inline style="grid-template-columns:..." on oral topic notes */
  /* minmax(0,1fr), not 1fr. `1fr` is shorthand for `minmax(auto, 1fr)`, and
     that `auto` minimum is the item's min-content size, so a single-column
     grid still sizes its one track to the widest thing inside it. On W07 that
     was a three-column table: the track resolved to 716px inside a 350px
     column on an iPhone 13, and BOTH cards in the grid inherited that width.
     .note-doc clips horizontally on mobile, so none of it was visible and no
     scrollbar appeared - but the clipped box is still a scroll container, so
     anything that moved scrollLeft (a focus, a scrollIntoView, the browser's
     own anchor jump) left the page shifted sideways with no way for the
     reader to put it back. That is the "page auto cropping to the left" a
     reader reported on 11 Sep 2026, on this exact topic. */
  .welcome-grid, .n-grid, .n-grid-3, .qcat-grid, [style*="grid-template-columns"] {
    grid-template-columns: minmax(0, 1fr) !important;
    gap: 10px;
  }
  /* Every child sits in that single column, whatever span it asked for.

     A card written with style="grid-column: span 2" to run full width on a
     desktop two-column grid does not fit a one-column grid. CSS does not clamp
     it: it creates an IMPLICIT second column, and the siblings before it are
     auto-placed side by side across the two. With min-width:0 on grid children
     (added 11 Sep so wide tables stop dragging tracks open) the first column
     can shrink to nothing, so the first card collapses to a sliver a character
     wide and its text stacks into a column hundreds of pixels tall.

     W01 "Overcurrent Protection - 3 Methods" on a phone: Method 1 vanished
     behind Method 2, and the row it inflated left a huge empty gap before
     Method 3. Reported by a reader with a screen recording on 14 Sep 2026.

     !important because the span is an inline style, and 1 / -1 rather than
     auto so a span of any size, on any of these grids, lands in the one
     column the phone layout actually has. */
  .welcome-grid > *, .n-grid > *, .n-grid-3 > *, .qcat-grid > *,
  [style*="grid-template-columns"] > * {
    grid-column: 1 / -1 !important;
  }
  /* Full-width reading on mobile */
  .note-doc {
    max-width: 100% !important;
    margin: 0;
    overflow-x: hidden;
    word-break: break-word;
    overflow-wrap: anywhere;
  }
  /* A value longer than the screen must wrap rather than run off the edge.
     .note-doc clips horizontally on mobile, so anything that overflows is not
     merely awkward, it is unreachable. Short values are unaffected: they fit
     on one line regardless. */
  .n-val { white-space: normal; }
  /* Same reasoning for anything else that can be wider than a phone. */
  .n-formula, pre, code { max-width: 100%; overflow-x: auto; overflow-wrap: anywhere; }
  
  /* Adjust typography & padding for mobile */
  .welcome h1 { font-size: 28px; }
  .welcome p { font-size: 14px; margin-bottom: 24px; }
  .welcome-card { padding: 16px; }
  
  .note-title { padding: 24px 16px; max-width: 100%; box-sizing: border-box; }
  .note-title h1 { font-size: 22px; word-break: break-word; }
  
  .quiz-topic-header { flex-direction: column; text-align: center; gap: 12px; padding: 20px 16px; }
  .quiz-topic-header .total { margin-left: 0; margin-top: 8px; }
  
  .quiz-q-area { padding: 20px 16px 12px; }
  .quiz-opts { padding: 12px 16px 16px; }
  /* Wraps. A hint beside three buttons does not fit a phone: at 280 and 320px
     the Prev / Skip / Next group ran 72px past the card, which clips it, so
     Next was half hidden after answering. Same markup in both apps. */
  .quiz-actions { padding: 12px 16px; flex-wrap: wrap; gap: 8px; }
  .quiz-actions .hint { flex: 1 1 auto; min-width: 0; }
  .quiz-actions > div { flex-wrap: wrap; justify-content: flex-end; margin-left: auto; }
  
  /* Table scrolls horizontally on its own; page stays locked in portrait */
  .n-table {
    font-size: 13px;
    display: block;
    max-width: 100%;
    overflow-x: auto;
    -webkit-overflow-scrolling: touch;
    white-space: nowrap;
  }
  .n-table th, .n-table td { padding: 10px 12px; }
  /* Overflow fixes for quiz/score screens */
  .score-screen, .duo-score-container { max-width: 100%; padding: 24px 16px; gap: 16px; border: none; border-radius: 0; box-shadow: none; }
  .duo-score-ill { font-size: 64px; }
  .duo-score-header h2 { font-size: 24px; }
  .duo-score-stat-box .n { font-size: 22px; }
  #quiz-active { max-width: 100%; }
  #quiz-home, #view-quiz-bank { max-width: 100%; }
  .n-formula {
    font-size: 14px;
    padding: 16px 14px;
    line-height: 1.7;
    overflow-x: auto;
    max-width: 100%;
    word-break: normal;
    overflow-wrap: break-word;
  }
  /* Desktop pulls the formula box back to the step's outer edge (level with
     the numbered circle) via a -38px margin that cancels the step's own
     left padding. On a narrow phone that reads as the box sitting left of
     where the step's own text starts. Keep it under the text instead. */
  .n-steps li .n-formula { margin-left: 0; }
  /* The solid red-circle emoji renders heavy and misaligned at small sizes on phones */
  .n-crit .icon { display: none; }
  /* Numerical card title/badge row: stack instead of squeezing the title into a
     sliver next to a long badge (e.g. a multi-month "By Year" pill) */
  .nc-header { flex-direction: column; gap: 8px !important; }
  .nc-badge { align-self: flex-start; white-space: normal !important; }

  /* ── Surveyor Q&A mobile ── */
  #view-sq-landing > div,
  #view-sq-grid > div { padding: 0; }
  #view-sq-landing > div > div:first-child { padding: 20px 0 16px; }
  #view-sq-landing > div > div:first-child h1 { font-size: 20px; }
  .sq-card { padding: 14px; max-width: 100%; box-sizing: border-box; }
  .sq-q { font-size: 14px; word-break: break-word; }
  .sq-a { padding: 12px; font-size: 13px; word-break: break-word; }
  .sq-bullet { flex-wrap: wrap; gap: 4px; }
  /* The row already wraps the label onto its own line, but a label longer than
     the screen ("Overload Relay (OLR) / Thermal Overload Relay:") still ran
     37px off a 280px phone. white-space alone did not fix it: with
     flex-shrink:0 a flex item keeps its one-line width even when allowed to
     wrap. max-width caps that width at the row, so the text breaks. */
  .sq-label { font-size: 12px; white-space: normal; flex-shrink: 1; max-width: 100%; }
  .sq-bullet-text { font-size: 13px; }
  .sq-para { font-size: 13px; }
  .sq-badge-surveyor, .sq-badge-topic, .sq-badge-mmd { font-size: 10px; padding: 3px 8px; }
  .sq-header { flex-wrap: wrap; }
}

.sb-spacer{flex:1}

/* ─── SVG ICONS ─── */
.svg-ic {
  width: 1.2em;
  height: 1.2em;
  stroke: currentColor;
  fill: none;
  stroke-width: 2;
  stroke-linecap: round;
  stroke-linejoin: round;
  vertical-align: text-bottom;
}
.sc-icon svg, .wc-icon svg {
  width: 1em;
  height: 1em;
  display: block;
}

/* ─── GAMIFIED SCORE SCREEN (DUOLINGO STYLE) ─── */
.duo-score-container {
    text-align: center;
    padding: 40px 32px;
    background: var(--surface);
    border: 1px solid var(--border2);
    border-radius: var(--r12);
    max-width: 480px;
    margin: 0 auto;
    box-shadow: 0 12px 40px rgba(0,0,0,0.25);
    
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 24px;
}
.duo-score-ill {
    font-size: 80px;
    line-height: 1;
    
    filter: drop-shadow(0 10px 15px rgba(0,0,0,0.3));
    margin-bottom: -10px;
}
.duo-score-header h2 {
    font-size: 32px;
    font-weight: 900;
    margin: 0 0 8px 0;
    letter-spacing: -0.5px;
}
.duo-score-header p {
    font-size: 16px;
    color: var(--text2);
    margin: 0;
}
.duo-score-stats {
    display: flex;
    gap: 12px;
    width: 100%;
}
.duo-score-stat-box {
    flex: 1;
    background: var(--surface2);
    border: 2px solid var(--border);
    border-radius: 16px;
    padding: 16px 8px;
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 4px;
    transition: transform 0.2s;
}

.duo-score-stat-box .n {
    font-size: 28px;
    font-weight: 800;
}
.duo-score-stat-box .l {
    font-size: 12px;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 1px;
    color: var(--text2);
}
.duo-score-actions {
    width: 100%;
    display: flex;
    flex-direction: column;
    gap: 12px;
    margin-top: 8px;
}
.duo-btn {
    width: 100%;
    padding: 16px;
    font-size: 18px;
    font-weight: 800;
    border-radius: 16px;
    border: none;
    cursor: pointer;
    text-transform: uppercase;
    letter-spacing: 1px;
    transition: background 0.2s, color 0.2s, border-color 0.2s, opacity 0.2s;
}
.duo-btn-primary {
    background: var(--green);
    color: #fff;
    box-shadow: 0 6px 0 #1b873f;
}
.duo-btn-primary:active {
    transform: translateY(6px);
    box-shadow: 0 0 0 #1b873f;
}
.duo-btn-primary.needs-practice {
    background: var(--orange);
    box-shadow: 0 6px 0 #b35900;
}
.duo-btn-primary.needs-practice:active {
    transform: translateY(6px);
    box-shadow: 0 0 0 #b35900;
}
.duo-btn-secondary {
    background: transparent;
    color: var(--text2);
    border: 2px solid var(--border2);
}
.duo-btn-secondary:hover {
    background: var(--surface2);
    color: var(--text);
}
.duo-btn-secondary:active {
    background: var(--border2);
}

/* ── Notes Search ─────────────────────────────────────── */
.search-results-dropdown {
    display: none;
    position: absolute;
    top: calc(100% + 6px);
    left: 0;
    right: 0;
    background: var(--surface);
    border: 1px solid var(--border2);
    border-radius: 14px;
    z-index: 200;
    max-height: 340px;
    overflow-y: auto;
    box-shadow: 0 16px 48px rgba(0,0,0,0.65), 0 4px 12px rgba(0,0,0,0.4);
    overscroll-behavior: contain;
}
.sr-item {
    display: flex;
    align-items: flex-start;
    gap: 10px;
    padding: 11px 14px;
    cursor: pointer;
    border-bottom: 1px solid var(--border);
    transition: background 0.12s;
}
.sr-item:last-of-type { border-bottom: none; }
.sr-item:hover { background: var(--surface2); }
.sr-badge {
    flex-shrink: 0;
    font-size: 10px;
    font-weight: 700;
    background: var(--blue-dim);
    color: var(--blue);
    border: 1px solid var(--blue-border);
    border-radius: 6px;
    padding: 2px 7px;
    margin-top: 2px;
    letter-spacing: .3px;
}
.sr-content { flex: 1; min-width: 0; }
.sr-heading {
    font-size: 13px;
    font-weight: 600;
    color: var(--text);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    line-height: 1.4;
}
.sr-mark {
    background: var(--blue-dim);
    color: var(--blue);
    border-radius: 3px;
    padding: 0 2px;
    font-style: normal;
}
.sr-snippet {
    font-size: 12px;
    color: var(--text2);
    margin-top: 3px;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    line-height: 1.4;
}
.sr-empty, .sr-indexing {
    padding: 14px 16px;
    text-align: center;
    color: var(--text2);
    font-size: 13px;
}
.sr-indexing {
    border-top: 1px solid var(--border);
    font-size: 11px;
    color: var(--text3);
    padding: 8px 14px;
    text-align: left;
}
.sr-meta {
    font-size: 11px;
    color: var(--text3);
    margin-top: 2px;
    font-weight: 500;
}

/* ── Global search panel scrollbar ──────────────────────── */
.gsearch-scroll {
    overflow-y: auto;
    overscroll-behavior: contain;
}
.gsearch-scroll::-webkit-scrollbar,
.search-results-dropdown::-webkit-scrollbar {
    width: 4px;
}
.gsearch-scroll::-webkit-scrollbar-track,
.search-results-dropdown::-webkit-scrollbar-track {
    background: transparent;
    margin: 6px 0;
}
.gsearch-scroll::-webkit-scrollbar-thumb,
.search-results-dropdown::-webkit-scrollbar-thumb {
    background: var(--border2);
    border-radius: 4px;
}
.gsearch-scroll::-webkit-scrollbar-thumb:hover,
.search-results-dropdown::-webkit-scrollbar-thumb:hover {
    background: var(--text3);
}

/* ── Sidebar search filter dropdown ─────────────────────── */
.gsf-opt {
    display: block;
    width: 100%;
    padding: 9px 14px;
    background: transparent;
    border: none;
    color: var(--text2);
    font-size: 13px;
    font-weight: 500;
    text-align: left;
    cursor: pointer;
    transition: background 0.12s, color 0.12s;
}
.gsf-opt:hover {
    background: var(--surface2);
    color: var(--text);
}
.gsf-opt + .gsf-opt {
    border-top: 1px solid var(--border);
}

/* ═══════════════ SURVEYOR Q&A PREMIUM STYLING ═══════════════ */
.sq-landing-card:hover { border-color: var(--purple) !important; box-shadow: 0 14px 30px rgba(0,0,0,.18) !important; }
.sq-landing-card:hover .wc-icon { filter: drop-shadow(0 8px 12px rgba(168,85,247,0.6)) !important; }
.sq-back-btn { border-color: var(--purple) !important; color: var(--purple) !important; }
.sq-oral-card { background: linear-gradient(135deg, var(--surface) 60%, rgba(168,85,247,.08)); border-color: rgba(168,85,247,.35) !important; }
.sq-oral-card h2,.sq-oral-card h3 { color: var(--purple); }
.sq-oral-card:hover { border-color: var(--purple) !important; box-shadow: 0 14px 30px rgba(0,0,0,.18) !important; background: linear-gradient(135deg, var(--surface) 40%, rgba(168,85,247,.14)) !important; }
.sq-oral-card:hover .wc-icon { filter: drop-shadow(0 8px 12px rgba(168,85,247,0.7)) !important; }
.sq-card { background: var(--surface); border: 1px solid var(--border); border-radius: var(--r12); padding: 20px; margin-bottom: 16px; box-shadow: 0 4px 12px rgba(0,0,0,0.05); transition: transform 0.2s, box-shadow 0.2s; }
.sq-card:hover { transform: translateY(-2px); box-shadow: 0 8px 24px rgba(0,0,0,0.08); }
.sq-header { display: flex; justify-content: space-between; align-items: flex-start; margin-bottom: 12px; gap: 12px; }
.sq-badges { display: flex; gap: 8px; flex-wrap: wrap; }
.sq-badge-surveyor { background: var(--purple-dim); color: var(--purple); padding: 4px 10px; border-radius: 20px; font-size: 11px; font-weight: 700; text-transform: uppercase; letter-spacing: 0.5px; }
.sq-badge-topic { background: var(--surface3); color: var(--text2); padding: 4px 10px; border-radius: 20px; font-size: 11px; font-weight: 600; }
/* MMD centre the question was asked at (q.mmd). Themed on both sides. */
.sq-badge-mmd { background: var(--blue-dim); color: var(--blue); border: 1px solid var(--blue-border); padding: 3px 9px; border-radius: 20px; font-size: 11px; font-weight: 700; }
.sq-a-none { font-size: 13px; font-style: italic; color: var(--text3); }
.sq-q { font-size: 16px; font-weight: 700; color: var(--text); line-height: 1.5; margin-bottom: 16px; }
.sq-a { font-size: 14px; color: var(--text); line-height: 1.6; background: var(--surface2); padding: 16px; border-radius: var(--r8); border-left: 4px solid var(--purple); }
.sq-bullet { display: flex; gap: 8px; align-items: baseline; padding: 6px 0; }
.sq-label { color: var(--purple); font-weight: 700; font-size: 13px; white-space: nowrap; flex-shrink: 0; }
.sq-bullet-text { color: var(--text); }
.sq-numbered { display: flex; gap: 10px; align-items: baseline; padding: 6px 0; }
.sq-num { color: var(--orange); font-weight: 700; font-size: 13px; flex-shrink: 0; min-width: 20px; }
.sq-para { padding: 6px 0; color: var(--text); }

/* ── Oral Scroll Hint ── */
@keyframes osh-enter { from{opacity:0;transform:translateX(-50%) translateY(24px)} to{opacity:1;transform:translateX(-50%) translateY(0)} }
@keyframes osh-exit  { to{opacity:0;transform:translateX(-50%) translateY(16px)} }
@keyframes osh-bounce{ 0%,100%{transform:translateY(0)} 50%{transform:translateY(5px)} }
@keyframes osh-pulse { 0%,100%{box-shadow:0 8px 28px rgba(168,85,247,0.5),0 0 0 0 rgba(168,85,247,0.5)} 60%{box-shadow:0 8px 28px rgba(168,85,247,0.5),0 0 0 10px rgba(168,85,247,0)} }
#oral-scroll-hint.osh-show { display:flex !important; animation: osh-enter 0.45s cubic-bezier(0.34,1.56,0.64,1) forwards; }
#oral-scroll-hint.osh-hide { animation: osh-exit 0.3s ease forwards; }
#osh-arrow { animation: osh-bounce 1.1s ease-in-out infinite; }
#osh-pill { animation: osh-pulse 2s ease-in-out infinite; }

.sq-surveyor-card { background: var(--surface); border: 1px solid var(--border); border-radius: var(--r12); padding: 20px; cursor: pointer; transition: transform 0.2s, border-color 0.2s; display: flex; flex-direction: column; gap: 8px; height: 100%; box-shadow: 0 4px 12px rgba(0,0,0,0.03); }
.sq-surveyor-card:hover { border-color: var(--orange); transform: translateY(-4px); box-shadow: 0 10px 20px rgba(245, 158, 11, 0.1); }
.sq-surveyor-name { font-size: 18px; font-weight: 800; color: var(--text); display: flex; align-items: center; gap: 8px; }
.sq-surveyor-stat { font-size: 13px; color: var(--text2); }
/* max-width: a select is as wide as its longest option, and "T01 - Alternators
   & Generators (58)" made both Surveyor Q&A filters 83-98px wider than a 360px
   phone, with the arrow and right edge cut off by .note-doc. */
.sq-topic-select { background: var(--surface); color: var(--text); border: 1px solid var(--border2); border-radius: var(--r8); padding: 7px 12px; font-size: 13px; font-weight: 600; cursor: pointer; max-width: 100%; }
.sq-topic-link { color: var(--blue); font-weight: 700; text-decoration: underline; text-underline-offset: 2px; cursor: pointer; }
.sq-topic-link:hover { color: var(--purple); }
.sq-topic-select:focus { outline: 2px solid var(--purple); outline-offset: 1px; }

/* ══════════════════════════════════════════
   APP GUIDE
══════════════════════════════════════════ */
#guide-overlay { position:fixed; inset:0; z-index:9000; display:none; pointer-events:all; }

#guide-spotlight {
    position: fixed; z-index: 9001; pointer-events: none; display: none;
    border: 2px solid rgba(168,85,247,0.75);
    box-shadow: 0 0 0 9999px rgba(0,0,0,0.76), 0 0 0 5px rgba(168,85,247,0.12), 0 0 32px rgba(168,85,247,0.3);
}

#guide-tooltip {
    /* Above the sidebar's temporary 9003 during sidebar steps, or the tooltip
       would slide back underneath the thing it is anchored to. */
    position: fixed; z-index: 9010; display: none;
    background: var(--surface);
    border: 1px solid var(--border2);
    border-radius: 16px;
    padding: 18px 20px 16px;
    width: min(300px, calc(100vw - 32px));
    box-shadow: 0 24px 64px rgba(0,0,0,0.65), 0 4px 16px rgba(0,0,0,0.3);
}
.guide-tt-header { display:flex; justify-content:space-between; align-items:center; margin-bottom:10px; }
.guide-tt-stepcount { font-size:11px; font-weight:700; color:var(--purple); text-transform:uppercase; letter-spacing:0.8px; }
.guide-tt-skip { background:none; border:none; color:var(--text3); font-size:11px; cursor:pointer; padding:0; font-family:inherit; }
.guide-tt-skip:hover { color:var(--text2); }
.guide-tt-title { font-size:15px; font-weight:800; color:var(--text); margin-bottom:7px; line-height:1.3; }
.guide-tt-body { font-size:13px; color:var(--text2); line-height:1.6; margin-bottom:16px; }
.guide-tt-footer { display:flex; align-items:center; justify-content:space-between; gap:12px; }
.guide-btn-next { background:var(--purple); border:none; color:var(--on-accent); padding:8px 18px; border-radius:8px; font-size:13px; font-weight:700; cursor:pointer; font-family:inherit; transition:opacity 0.15s, transform 0.15s; white-space:nowrap; }
.guide-btn-next:hover { opacity:0.85; transform:translateY(-1px); }

#guide-dots { display:flex; gap:5px; align-items:center; }
.guide-dot { width:6px; height:6px; border-radius:50%; background:var(--border2); transition:all 0.25s ease; flex-shrink:0; }
.guide-dot.active { width:18px; border-radius:4px; background:var(--purple); }

#guide-slide-wrap {
    position: fixed; inset: 0; z-index: 9001;
    background: rgba(0,0,0,0.9);
    backdrop-filter: blur(12px); -webkit-backdrop-filter: blur(12px);
    align-items: center; justify-content: center;
    padding: 24px; box-sizing: border-box;
}
#guide-slide-card {
    background: var(--surface);
    border: 1px solid rgba(255,255,255,0.06);
    border-radius: 22px;
    padding: 36px 32px;
    max-width: 420px; width: 100%;
    box-shadow: 0 48px 96px rgba(0,0,0,0.6), 0 0 0 1px rgba(168,85,247,0.08);
}
.guide-btn-primary {
    display: block; width: 100%;
    padding: 13px 24px;
    background: var(--purple); border: none; border-radius: 10px;
    color: var(--on-accent); font-size: 15px; font-weight: 700; cursor: pointer;
    font-family: inherit; transition: opacity 0.15s, transform 0.15s;
    box-sizing: border-box;
}
.guide-btn-primary:hover { opacity:0.87; transform:translateY(-1px); }
.guide-btn-support {
    display: block; width: 100%; box-sizing: border-box;
    padding: 13px 24px;
    background: linear-gradient(135deg, rgba(168,85,247,1), rgba(139,60,220,1));
    border: none; border-radius: 10px;
    color: #fff; font-size: 15px; font-weight: 700; cursor: pointer;
    font-family: inherit; text-decoration: none; text-align: center;
    transition: opacity 0.15s, transform 0.15s;
    box-shadow: 0 6px 24px rgba(168,85,247,0.4);
}
.guide-btn-support:hover { opacity:0.88; transform:translateY(-1px); }
.guide-btn-text { background:none; border:none; color:var(--text3); font-size:13px; cursor:pointer; font-family:inherit; padding:0; }
.guide-btn-text:hover { color:var(--text2); text-decoration:underline; }
.guide-stat-box { background:var(--surface2); border:1px solid var(--border); border-radius:10px; padding:10px 14px; min-width:68px; }
.guide-stat-num { font-size:20px; font-weight:800; color:var(--purple); line-height:1; }
.guide-stat-lbl { font-size:11px; color:var(--text3); margin-top:3px; font-weight:600; text-transform:uppercase; letter-spacing:0.5px; }

#guide-relaunch-btn {
    width: 28px; height: 28px; border-radius: 50%;
    background: var(--surface2); border: 1.5px solid var(--border);
    color: var(--text2); font-size: 13px; font-weight: 700;
    cursor: pointer; display: flex; align-items: center; justify-content: center;
    flex-shrink: 0; transition: border-color 0.15s, color 0.15s;
}
#guide-relaunch-btn:hover { border-color: var(--purple); color: var(--purple); }

@media (max-width: 768px) {
    #guide-slide-card { padding: 28px 22px; }
    #guide-tooltip { width: min(280px, calc(100vw - 24px)); padding: 14px 16px 14px; }
    .guide-tt-body { font-size: 12.5px; margin-bottom: 12px; }
    /* Hide logo subtitle on mobile - prevents topbar overflow.
       Scoped to .logo-sub specifically: a plain ".logo span" selector here
       previously also matched .logo-elec ("Elec"), silently hiding it on
       every screen ≤768px since it's a span too. */
    .logo .logo-sub { display: none; }
    /* Video tab segment: tighter padding so two buttons fit on small screens */
    .qb-seg-btn { padding: 9px 14px; }
    /* Score breakdown: 2 cols on mobile (3 cols at ~90px each is too tight) */
    .score-breakdown { grid-template-columns: 1fr 1fr; }
}

/* ── Floating video player - mobile layout ── */
@media (max-width: 600px) {
    /* Stack player on top, playlist scrollable below */
    .vid-float-inner { flex-direction: column; }
    .vid-float-player { flex: none; width: 100%; }
    .vid-float-sidebar {
        flex: 0 0 auto;
        border-left: none;
        border-top: 1px solid var(--border2);
        max-height: 36vh;
    }
    /* Use dvh so iOS browser chrome doesn't clip the bottom */
    .vid-float-box { max-height: 90dvh; }
    /* Bigger close button tap target */
    .vid-float-close {
        padding: 10px 16px;
        font-size: 18px;
        min-width: 44px;
        min-height: 44px;
        display: flex;
        align-items: center;
        justify-content: center;
    }
}

/* ── VIDEOS TAB STYLES ── */
.vid-lang-chips { display: flex; flex-wrap: wrap; gap: 6px; margin-bottom: 12px; }
.vid-lang-chip {
    padding: 5px 12px;
    border-radius: 20px;
    border: 1px solid var(--border2);
    background: var(--surface2);
    color: var(--text3);
    font-size: 12px;
    font-weight: 600;
    cursor: pointer;
    transition: background 0.15s, color 0.15s;
}
.vid-lang-chip:hover { background: var(--surface); color: var(--text); }
.vid-lang-chip.active { background: var(--blue); color: var(--on-accent); border-color: var(--blue); }
.vid-list { display: flex; flex-direction: column; gap: 4px; }
.vid-list-item {
    display: flex;
    align-items: center;
    gap: 12px;
    padding: 11px 14px;
    border-radius: 10px;
    background: var(--surface2);
    border: 1px solid var(--border2);
    cursor: pointer;
    text-align: left;
    width: 100%;
    transition: background 0.15s;
}
.vid-list-item:hover { background: var(--surface); }
.vid-list-icon { color: var(--blue); font-size: 13px; flex-shrink: 0; }
.vid-list-label { font-size: 13px; font-weight: 600; color: var(--text); flex: 1; }
.vid-lang-badge {
    font-size: 10px;
    font-weight: 700;
    padding: 2px 7px;
    border-radius: 10px;
    background: rgba(59,130,246,0.12);
    color: var(--blue);
    flex-shrink: 0;
    letter-spacing: 0.03em;
}

/* Floating player */
.vid-float-backdrop {
    position: fixed;
    inset: 0;
    background: rgba(0,0,0,0.65);
    z-index: 1200;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 16px;
}
.vid-float-box {
    background: var(--surface);
    border-radius: 14px;
    width: min(92vw, 920px);
    max-height: 85vh;
    display: flex;
    flex-direction: column;
    overflow: hidden;
    box-shadow: 0 24px 64px rgba(0,0,0,0.55);
}
.vid-float-topbar {
    display: flex;
    align-items: center;
    justify-content: flex-end;
    padding: 8px 10px;
    border-bottom: 1px solid var(--border2);
    flex-shrink: 0;
}
.vid-float-close {
    background: none;
    border: none;
    color: var(--text3);
    font-size: 16px;
    cursor: pointer;
    padding: 4px 8px;
    border-radius: 6px;
    line-height: 1;
}
.vid-float-close:hover { background: var(--surface2); color: var(--text); }
.vid-float-inner {
    display: flex;
    min-height: 0;
    flex: 1;
}
.vid-float-player {
    flex: 1 1 65%;
    display: flex;
    flex-direction: column;
    min-width: 0;
}
.vid-float-iframe-wrap {
    position: relative;
    width: 100%;
    padding-bottom: 56.25%;
    flex-shrink: 0;
}
.vid-float-iframe-wrap iframe {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    border: 0;
}
.vid-float-now-playing {
    padding: 10px 14px;
    font-size: 12px;
    font-weight: 600;
    color: var(--text);
    border-top: 1px solid var(--border2);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    flex-shrink: 0;
}
.vid-float-sidebar {
    flex: 0 0 35%;
    border-left: 1px solid var(--border2);
    overflow-y: auto;
    display: flex;
    flex-direction: column;
}
.vid-float-pl-item {
    display: flex;
    align-items: flex-start;
    gap: 10px;
    padding: 11px 14px;
    cursor: pointer;
    border-bottom: 1px solid var(--border2);
    border-left: none;
    border-right: none;
    border-top: none;
    width: 100%;
    text-align: left;
    background: none;
    transition: background 0.15s;
}
.vid-float-pl-item:hover { background: var(--surface2); }
.vid-float-pl-item.active { background: rgba(59,130,246,0.1); }
.vid-float-pl-icon { color: var(--blue); font-size: 11px; flex-shrink: 0; margin-top: 2px; }
.vid-float-pl-label { font-size: 12px; font-weight: 600; color: var(--text); line-height: 1.4; }

/* ── NOTE DIAGRAMS ── */
.note-diagram-wrap {
    margin: 18px 0;
    text-align: center;
}
.note-diagram-wrap img {
    max-width: min(100%, 560px);
    max-height: 300px;
    width: auto;
    height: auto;
    display: block;
    margin: 0 auto;
    border-radius: 10px;
    border: 1px solid var(--border2);
    background: #fff;
    cursor: zoom-in;
    transition: box-shadow .2s;
}
.note-diagram-wrap img:hover {
    box-shadow: 0 4px 24px rgba(59,130,246,.25);
}
/* The zoomed view is its own element appended to <body> (see _dgmOpen in
   app.js), not a class on the image where it sits. Faking the backdrop with a
   100vmax box-shadow on a position:fixed image failed because the image lives
   inside #content, which scrolls, and .note-doc, which clips horizontally on
   mobile: the shadow was cut off by an ancestor and the fixed element was
   positioned against it rather than the viewport, so the page and sidebar
   showed through. A real overlay on <body> escapes both. */
.dgm-lightbox {
  position: fixed; inset: 0; z-index: 10001;   /* above #content (9999) and the hw viewer (10000) */
  background: rgba(0,0,0,.93);
  display: flex; align-items: center; justify-content: center;
  padding: 16px; cursor: zoom-out;
  overscroll-behavior: contain;
}
.dgm-lightbox[hidden] { display: none; }
.dgm-lightbox-img {
  max-width: 96vw; max-height: 94vh;
  width: auto; height: auto;
  object-fit: contain;
  border-radius: 8px;
  /* Diagrams are line art on white; without this a dark theme shows them on
     a dark ground with the strokes barely visible. */
  background: #fff;
  box-shadow: 0 18px 60px rgba(0,0,0,.6);
}
/* Reference plates are whole pages, so fitting one to the screen makes its
   body text unreadable. These open fitted, then tap the page to go to 1:1 and
   pan; tapping the surround still closes. */
.dgm-lightbox.is-plate { align-items: flex-start; justify-content: center; overflow: auto; padding: 0; }
.dgm-lightbox.is-plate .dgm-lightbox-img { cursor: zoom-in; margin: 16px auto; }
.dgm-lightbox.is-plate.is-zoomed { justify-content: flex-start; }
.dgm-lightbox.is-plate.is-zoomed .dgm-lightbox-img {
  max-width: none; max-height: none;
  width: auto; height: auto;
  cursor: zoom-out;
  margin: 0;
  border-radius: 0;
}
.note-diagram-cap {
    font-size: 12px;
    color: var(--text3, #888);
    margin-top: 6px;
    font-style: italic;
}

/* ── Symbol grid ──────────────────────────────────────────────────────────
   For sets of small pictograms (IMO fire control plan symbols and the like),
   where the whole point is scanning a legend rather than studying one figure.
   Each tile is ~2 KB, so these deliberately do NOT carry data-blur: replacing
   them with 64 "tap to download" placeholders would cost far more than just
   sending them. The artwork is black and colour on white, so every tile keeps
   a white plate behind it and stays legible in dark mode. */
.sym-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(136px, 1fr));
    gap: 10px;
    margin: 14px 0 6px;
}
.sym {
    margin: 0;
    background: var(--surface2, #f7f8fa);
    border: 1px solid var(--border2, #e3e6ec);
    border-radius: 10px;
    padding: 8px 8px 9px;
    display: flex;
    flex-direction: column;
    align-items: center;
    text-align: center;
    transition: border-color .15s, box-shadow .15s;
}
.sym:hover { border-color: var(--blue, #3b82f6); box-shadow: 0 3px 14px rgba(59,130,246,.16); }
.sym img {
    width: 100%;
    height: 62px;
    object-fit: contain;
    background: #fff;
    border-radius: 7px;
    padding: 5px;
    cursor: zoom-in;
    display: block;
}
.sym figcaption {
    margin-top: 7px;
    font-size: 10.5px;
    line-height: 1.35;
    color: var(--text3, #8a93a6);
}
.sym figcaption b {
    display: block;
    font-size: 11px;
    color: var(--text2, #c8cedb);
    font-variant-numeric: tabular-nums;
    margin-bottom: 1px;
}

/* ── Plate strip ──────────────────────────────────────────────────────────
   For full-page reference sheets (GA drawings, manual pages). A whole A4 page
   inline renders its text at about 6pt on a phone, so these are shown as
   thumbnails cropped to the top of the page and opened full screen instead. */
/* Flex rather than fixed-width grid columns, so each tile's width follows its
   drawing: a landscape general-arrangement stays landscape and a portrait page
   stays portrait, all sharing one row height. A fixed column width forced every
   plate into the same portrait box and cropped the wide drawings. */
.plate-strip {
    display: flex;
    align-items: flex-start;
    gap: 12px;
    overflow-x: auto;
    -webkit-overflow-scrolling: touch;
    overscroll-behavior-x: contain;
    padding: 4px 2px 12px;
    margin: 12px 0 4px;
    scroll-snap-type: x proximity;
}
.plate {
    scroll-snap-align: start;
    flex: 0 0 auto;
    max-width: 340px;
    background: var(--surface2, #f7f8fa);
    border: 1px solid var(--border2, #e3e6ec);
    border-radius: 10px;
    overflow: hidden;
    display: flex;
    flex-direction: column;
    transition: border-color .15s, box-shadow .15s;
}
.plate:hover { border-color: var(--blue, #3b82f6); box-shadow: 0 3px 14px rgba(59,130,246,.16); }
.plate img {
    height: 150px;
    width: auto;
    max-width: 340px;
    min-width: 96px;
    object-fit: contain;
    background: #fff;
    cursor: zoom-in;
    display: block;
}
.plate-cap {
    font-size: 11px;
    line-height: 1.4;
    color: var(--text3, #8a93a6);
    padding: 7px 9px 8px;
    /* The caption must not stretch a narrow portrait tile wider than its
       drawing, so it is allowed to wrap inside whatever width the image sets. */
    max-width: 300px;
}
.plate-cap b { display: block; color: var(--text2, #c8cedb); font-size: 11.5px; margin-bottom: 1px; }
.plate-strip-note { font-size: 11.5px; color: var(--text3, #8a93a6); font-style: italic; margin: 0 0 2px; }

@media (max-width: 600px) {
    .sym-grid { grid-template-columns: repeat(auto-fill, minmax(104px, 1fr)); gap: 8px; }
    .sym img { height: 52px; }
    .plate img { height: 124px; max-width: 260px; }
    .plate, .plate-cap { max-width: 260px; }
}
@media(max-width:600px){
    .note-diagram-wrap img { max-width: 100%; }
}

/* Data Saver placeholder - the actual diagram, heavily blurred (a ~200-byte
   inline preview, not a network fetch), sitting under a dark scrim with a
   download button on top. Same pattern as WhatsApp/Telegram media messages:
   you see roughly what it is before choosing to spend the data on it. */
.dgm-placeholder {
    position: relative;
    max-width: min(100%, 560px);
    height: 200px;
    margin: 0 auto;
    border-radius: var(--r8, 8px);
    overflow: hidden;
    cursor: pointer;
    background: var(--surface2);
}
/* Two classes so this beats .note-diagram-wrap img's width:auto/height:auto -
   .dgm-blur-bg is an <img> living inside that same wrapper, and without the
   extra specificity here the generic rule was winning and rendering it at
   its natural ~28px size instead of filling the placeholder box. */
.dgm-placeholder .dgm-blur-bg {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    max-width: none;
    max-height: none;
    object-fit: cover;
    /* scale hides the soft edge the blur radius would otherwise leave visible */
    filter: blur(16px) saturate(1.15);
    transform: scale(1.2);
}
.dgm-overlay {
    position: absolute;
    inset: 0;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 10px;
    /* Darker at the center so the icon/label stay legible over any diagram's
       colors, lighter at the edges so the blurred preview still reads
       through - most of these diagrams are pale, technical-illustration
       backgrounds, not photos, so a flat dark scrim was crushing them. */
    background: radial-gradient(circle at center, rgba(0,0,0,.5) 0%, rgba(0,0,0,.5) 20%, rgba(0,0,0,.22) 70%);
    transition: background .15s;
}
.dgm-placeholder:hover .dgm-overlay, .dgm-placeholder:focus-visible .dgm-overlay {
    background: radial-gradient(circle at center, rgba(0,0,0,.6) 0%, rgba(0,0,0,.6) 20%, rgba(0,0,0,.32) 70%);
    outline: none;
}
.dgm-dl-icon {
    width: 44px;
    height: 44px;
    border-radius: 50%;
    background: rgba(255,255,255,.14);
    border: 1.5px solid rgba(255,255,255,.4);
    color: #fff;
    display: flex;
    align-items: center;
    justify-content: center;
    transition: background .15s, border-color .15s, transform .15s;
}
.dgm-placeholder:hover .dgm-dl-icon, .dgm-placeholder:focus-visible .dgm-dl-icon {
    background: var(--blue);
    border-color: var(--blue);
    transform: scale(1.08);
}
.dgm-dl-label { font-size: 12.5px; font-weight: 700; color: #fff; text-shadow: 0 1px 3px rgba(0,0,0,.5); }

/* ═══ THEME SWITCHER ═══ */
/* Data Saver toggle switch (profile menu) */
.ds-switch { position: relative; display: inline-block; width: 40px; height: 22px; flex-shrink: 0; cursor: pointer; }
.ds-switch input { opacity: 0; width: 0; height: 0; position: absolute; }
.ds-switch-track { position: absolute; inset: 0; background: #1A3050; border: 1px solid #2E5577; border-radius: 22px; transition: background .18s, border-color .18s; }
.ds-switch-track::before {
    content: ''; position: absolute; height: 16px; width: 16px; left: 2px; top: 1px;
    background: #fff; border-radius: 50%; transition: transform .18s;
    box-shadow: 0 1px 3px rgba(0,0,0,.35);
}
.ds-switch input:checked + .ds-switch-track { background: #C8A44A; border-color: #C8A44A; }
.ds-switch input:checked + .ds-switch-track::before { transform: translateX(18px); }
.ds-switch input:focus-visible + .ds-switch-track { outline: 2px solid #C8A44A; outline-offset: 2px; }

.theme-switcher{padding:10px 12px;display:flex;align-items:center;gap:6px;justify-content:center}
.theme-btn{width:38px;height:34px;border-radius:var(--r8);border:1px solid var(--border2);background:var(--surface2);font-size:15px;cursor:pointer;transition:border-color .15s,background .15s;display:flex;align-items:center;justify-content:center;flex:1;color:var(--text2)}
.theme-btn:hover{border-color:var(--border2);background:var(--surface3);color:var(--text)}
.theme-btn.t-active{border-color:var(--blue-border);background:var(--blue-dim);color:var(--blue)}
/* Gate overlay always stays dark - theme toggle doesn't reach inside */
#gate-overlay{--bg:#07080e;--surface:#0D1E33;--surface2:#0D1E33;--surface3:#132030;--border:#1A3050;--border2:#1A3050;--text:#F8FAFC;--text2:#CBD5E1;--text3:#94A3B8;--blue:#f59e0b;--blue-dim:rgba(245,158,11,.12);--blue-border:rgba(245,158,11,.35);--amber:#C8A44A}
/* The upgrade modal is a deliberate dark surface in every theme, gold on
   near-black, the same decision as the paywall above. Pinning the palette
   here is what makes that safe: both sides of every pair move together, so
   no theme can leave dark text on the dark scrim. */
#upgrade-modal{--bg:#040914;--surface:#0D1E33;--surface2:#0D1E33;--surface3:#132030;--border:#1A3050;--border2:#1A3050;--text:#F8FAFC;--text2:#CBD5E1;--text3:#94A3B8;--amber:#C8A44A;--green:#5DC87A;--green-dim:rgba(93,200,122,.14);--green-border:rgba(93,200,122,.35);--red:#E06C6C;--orange:#f59e0b}

/* Light theme global fixes */
[data-theme="light"] body{background:var(--bg);color:var(--text)}
/* Answer feedback text is tuned for a dark card (pale mint / pale red). On the
   near-white light-theme card those land around 1.3:1 contrast, effectively
   invisible right when the cadet needs to read which answer was right. Restate
   them as deep tones against the same 8%-alpha tint. */
[data-theme="light"] .qopt.correct .opt-text{color:#15803d!important}
[data-theme="light"] .qopt.wrong .opt-text{color:#b91c1c!important}
[data-theme="light"] .quiz-exp{background:rgba(37,99,235,.07);border-color:rgba(37,99,235,.25);color:var(--text)}
[data-theme="light"] .quiz-exp strong{color:var(--blue)}
[data-theme="light"] .note-title{background:linear-gradient(135deg,rgba(37,99,235,.08),rgba(124,58,237,.05))}
[data-theme="light"] .n-table{box-shadow:0 1px 6px rgba(0,0,0,.08)}

/* ═══ MOBILE HARDENING ═══════════════════════════════════════════════ */

/* iOS Safari auto-zooms the viewport when a focused input has font-size
   under 16px, and never zooms back out. Force 16px on touch devices only,
   so desktop keeps its tighter type scale. */
@media (max-width: 768px) {
  input[type="text"], input[type="email"], input[type="password"],
  input[type="search"], input[type="number"], input[type="date"],
  textarea, select {
    font-size: 16px !important;
  }
}

/* Notch / home-indicator safe areas (iPhone X+ and Android cutouts) */
@supports (padding: max(0px)) {
  #topbar { padding-left: max(20px, env(safe-area-inset-left));
            padding-right: max(20px, env(safe-area-inset-right)); }
  #sidebar { padding-bottom: env(safe-area-inset-bottom); }
  /* Adds the inset on top of the real design padding rather than replacing
     it - env(safe-area-inset-left/right) is 0px on virtually every device
     (it only matters in the landscape-notch edge case), so max(0px, ...)
     was silently zeroing out #content's actual ~48px horizontal padding on
     every device, at every screen size, not just notched phones. */
  #content { padding-bottom: max(24px, env(safe-area-inset-bottom));
             padding-left: calc(clamp(20px,4vw,48px) + env(safe-area-inset-left));
             padding-right: calc(clamp(20px,4vw,48px) + env(safe-area-inset-right)); }
}

/* Touch targets: WCAG 2.5.5 asks for 44x44 minimum */
@media (hover: none) and (pointer: coarse) {
  .tin-pill, .qb-seg-btn, .vid-lang-chip, .theme-btn { min-height: 40px; }
  .quiz-opt { min-height: 48px; }
  button, [role="button"] { touch-action: manipulation; }
}

/* Landscape phones are short - reclaim vertical space */
@media (max-height: 480px) and (orientation: landscape) {
  #topbar { height: 48px; }
  #sidebar { top: 0; height: 100svh; width: 280px; }
  #sidebar-overlay { top: 0; }
  .note-title { padding: 14px 16px; }
  .welcome h1 { font-size: 22px; }
  /* A phone on its side is 740-956px wide, so it is ABOVE the 768px
     breakpoint and misses the mobile wrapping rules entirely, even though it
     is still a phone. .n-val is white-space:nowrap by default, which makes a
     long value like "500 V, 1000 V, 2500 V or 5000 V" one unbreakable run and
     pushes the column wider than the screen. Same reasoning as the ≤768px
     rule; short values are unaffected because they fit on one line anyway. */
  .n-val { white-space: normal; }
  .n-formula, pre, code { max-width: 100%; overflow-x: auto; overflow-wrap: anywhere; }
}

/* Very small phones (iPhone SE 1st gen / Galaxy Fold cover ≈320px) */
@media (max-width: 360px) {
  #content { padding: 12px; }
  .note-title { padding: 18px 12px; }
  .note-title h1 { font-size: 19px; }
  .welcome h1 { font-size: 24px; }
  .n-table th, .n-table td { padding: 8px 9px; font-size: 12px; }
  .score-breakdown { grid-template-columns: 1fr; }
  #topbar { gap: 8px; padding: 0 12px; }
  /* The logo is white-space:nowrap and flex-shrink:0, so on the narrowest
     screens nothing in the topbar could give way and the row simply grew. The
     Sponsorship topbar carries a notification bell the COC one does not, which
     is enough to push it over: on a 280px Galaxy Fold cover the account button
     ended 32px past the right edge, clipped by body's overflow-x:hidden and
     therefore unreachable, with the page able to hold a sideways scroll the
     reader could not undo. Letting the wordmark shrink and truncate keeps
     every control on screen; the logo image and both buttons keep their size. */
  /* Shrink the wordmark rather than truncate it: at 320px and 360px the full
     "Elec-Buddy" still fits at this size, so nobody sees a clipped brand. The
     flex-shrink/min-width/ellipsis below is the last resort for a 280px Fold
     cover, where something has to give and a shortened wordmark is a better
     loss than an account button that has left the screen. */
  #topbar .logo { font-size: 16px; flex-shrink: 1; min-width: 0; overflow: hidden; }
  #topbar .logo .logo-mark { height: 30px; }
  #topbar .logo .logo-word { overflow: hidden; text-overflow: ellipsis; }
}

/* ── HANDWRITTEN SOLUTION SHEETS ────────────────────────────────
   Thumbnail in the "Handwritten Solution" tab, plus the full-screen
   zoom/pan viewer it opens. These sheets are dense landscape worked
   solutions, so the inline thumbnail is only ever an invitation to open
   the viewer, never something you are expected to read in place. */
.hw-figure { margin: 0; text-align: center; }
/* Until a src exists the <img> would paint as a broken-image box with its
   alt text written out in full. Hide it and its caption; the Data Saver
   button (or the tab-open reveal) is the only thing that should show. */
.hw-figure.hw-pending .hw-img,
.hw-figure.hw-pending .hw-cap { display: none; }
.hw-img {
    max-width: 100%;
    height: auto;
    display: block;
    margin: 0 auto;
    border-radius: 8px;
    border: 1px solid var(--border2);
    background: #fff;
    cursor: zoom-in;
    transition: box-shadow .2s;
}
.hw-img:hover { box-shadow: 0 4px 24px rgba(59,130,246,.25); }
.hw-cap {
    font-size: 12px;
    color: var(--text3, #888);
    margin-top: 8px;
    font-style: italic;
}
.hw-ds-btn {
    display: block;
    width: 100%;
    padding: 14px;
    margin-bottom: 10px;
    font: inherit;
    font-size: 13px;
    color: var(--text);
    background: var(--surface3);
    border: 1px dashed var(--border);
    border-radius: 8px;
    cursor: pointer;
}
.hw-ds-btn:hover { border-color: var(--blue); color: var(--blue); }

body.hw-open { overflow: hidden; }
.hw-viewer {
    position: fixed;
    inset: 0;
    z-index: 10000;
    background: rgba(0,0,0,.94);
    display: flex;
    align-items: center;
    justify-content: center;
}
.hw-viewer[hidden] { display: none; }
.hw-stage {
    position: absolute;
    inset: 0;
    display: flex;
    align-items: center;
    justify-content: center;
    overflow: hidden;
    /* Own the gesture: without this the browser hijacks pinch as a page
       zoom and the viewer never sees the second pointer. */
    touch-action: none;
    cursor: grab;
}
.hw-stage.is-zoomed { cursor: grab; }
.hw-stage.is-zoomed:active { cursor: grabbing; }
.hw-stage-img {
    max-width: 100vw;
    max-height: 100vh;
    width: auto;
    height: auto;
    object-fit: contain;
    transform-origin: center center;
    will-change: transform;
    user-select: none;
    -webkit-user-drag: none;
    background: #fff;
}
.hw-bar {
    position: absolute;
    bottom: max(18px, env(safe-area-inset-bottom));
    left: 50%;
    transform: translateX(-50%);
    display: flex;
    align-items: center;
    gap: 6px;
    padding: 6px;
    border-radius: 999px;
    background: rgba(20,26,36,.92);
    border: 1px solid rgba(255,255,255,.14);
    box-shadow: 0 6px 24px rgba(0,0,0,.5);
}
.hw-btn, .hw-close {
    min-width: 44px;
    min-height: 44px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    font: inherit;
    font-size: 20px;
    line-height: 1;
    color: #fff;
    background: transparent;
    border: 0;
    border-radius: 999px;
    cursor: pointer;
}
.hw-btn-wide { font-size: 13px; padding: 0 14px; }
.hw-btn:hover, .hw-close:hover { background: rgba(255,255,255,.14); }
.hw-btn:focus-visible, .hw-close:focus-visible { outline: 2px solid var(--blue); outline-offset: 2px; }
.hw-zoom {
    min-width: 56px;
    text-align: center;
    font-size: 13px;
    font-variant-numeric: tabular-nums;
    color: rgba(255,255,255,.85);
}
.hw-close {
    position: absolute;
    top: max(14px, env(safe-area-inset-top));
    right: 14px;
    font-size: 28px;
    background: rgba(20,26,36,.92);
    border: 1px solid rgba(255,255,255,.14);
}
@media (prefers-reduced-motion: reduce) {
    .hw-img { transition: none; }
}
.hw-note { margin-top: 14px; text-align: left; }

/* ── Feedback / bug report form ─────────────────────────────────
   Lives in index.html's modal. Sized so every control clears the 44px
   touch floor at phone widths without a separate mobile rule. */
.fb-lbl {
    display: block; font-size: 11px; font-weight: 700; letter-spacing: .05em;
    text-transform: uppercase; color: var(--text3); margin-bottom: 6px;
}
.fb-in {
    width: 100%; box-sizing: border-box; min-height: 44px;
    background: var(--surface2); border: 1px solid var(--border); border-radius: 8px;
    color: var(--text); font-size: 14px; font-family: inherit;
    padding: 11px 12px; outline: none;
}
.fb-in:focus { border-color: var(--blue); }
.fb-hint { font-size: 11.5px; color: var(--text3); line-height: 1.5; margin-top: 6px; }
.fb-file-row {
    display: flex; align-items: center; justify-content: space-between; gap: 10px;
    background: var(--surface2); border: 1px solid var(--border); border-radius: 6px;
    padding: 8px 10px; margin-bottom: 6px; font-size: 12px; color: var(--text2);
}
.fb-file-row .nm { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.fb-file-row .sz { color: var(--text3); flex-shrink: 0; font-variant-numeric: tabular-nums; }
.fb-file-row.bad { border-color: var(--red-border); color: var(--red); }

/* ── UPGRADE MODAL ───────────────────────────────────────────
   Moved out of a <style> block inside app/index.html on 12 Sep 2026, when
   checkout became shared. The modal is injected by app/checkout.js into
   whichever page opens it, so its styling has to live somewhere both pages
   already load - and both load this file. Left in index.html it would have
   rendered the Sponsorship app an unstyled modal. */
  .up-track-tab {
    flex: 1; background: rgba(13,30,51,0.7); border: 1px solid #1A3050; border-radius: 8px;
    padding: 9px 6px; font-size: 11.5px; font-weight: 700; letter-spacing: 0.06em;
    color: var(--text3); cursor: pointer; transition: border-color .15s, background .15s, color .15s;
    font-family: inherit;
  }
  .up-track-tab .utt-brand {
    display: block; font-size: 9px; font-weight: 600;
    letter-spacing: 0.04em; opacity: 0.7; margin-top: 2px;
    text-transform: uppercase;
  }
  .up-track-tab:hover { background: rgba(20,42,68,0.8); }
  .up-track-tab.active { background: #C8A44A; border-color: var(--amber); color: #070D1A; }

  /* The modal was capped at 520px, which is right for one column of cards but
     leaves three at about 160px each: too narrow for a price, a line of
     description and a Pay button. It widens only where there is room to widen,
     so the phone layout is untouched. */
  .up-modal-inner { width: 100%; max-width: 520px; margin-top: 20px; }
  @media (min-width: 900px) { .up-modal-inner { max-width: 880px; } }

  /* Three plans, side by side on a wide screen.
     Stacked, they cannot be compared without scrolling, which is the one job
     a pricing table has. Auto-fit rather than a fixed three columns so it
     collapses to two and then one on its own as the space runs out, with no
     breakpoint to keep in step with the modal width. */
  #up-tier-cards {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));
    gap: 12px;
    margin-bottom: 24px;
    align-items: stretch;
  }
  .up-plan-card {
    background: rgba(13,30,51,0.7);
    border: 1px solid #1A3050;
    border-radius: 12px;
    padding: 18px 18px 16px;
    position: relative;
    transition: border-color .15s, background .15s;
    /* Column layout so the Pay button sits on the baseline in every card even
       when the descriptions run to different lengths. */
    display: flex;
    flex-direction: column;
    gap: 9px;
  }
  .up-plan-card .up-card-gets { flex: 1 0 auto; }
  .up-plan-card:hover { background: rgba(20,42,68,0.8); }
  .up-plan-card-best { border-color: var(--amber); }
  .up-ribbon {
    position: absolute; top: -11px; left: 50%; transform: translateX(-50%);
    background: #C8A44A; color: #070D1A; font-size: 9.5px; font-weight: 700;
    padding: 3px 12px; border-radius: 20px; white-space: nowrap;
    letter-spacing: 0.08em; text-transform: uppercase;
  }
  .up-ribbon-promo { background: #5DC87A; }
  /* Offer banner. Said once above the cards rather than repeated on each,
     which also frees the cards to keep their own Best Value badge. */
  .up-offer {
    display: flex; align-items: center; justify-content: center; gap: 10px;
    flex-wrap: wrap; text-align: center;
    background: var(--green-dim); border: 1px solid var(--green-border);
    border-radius: 10px; padding: 9px 14px; margin: 0 0 18px;
  }
  .up-offer-tag {
    background: var(--green); color: var(--on-accent);
    font-size: 9.5px; font-weight: 800; letter-spacing: .06em; text-transform: uppercase;
    padding: 3px 9px; border-radius: 20px; white-space: nowrap;
  }
  .up-offer-desc { font-size: 13.5px; font-weight: 600; color: var(--text); line-height: 1.45; }
  /* The deadline. Quiet when it is weeks away, loud in the last few days,
     because that is when it is actually a reason to decide. */
  .up-offer-ends {
    font-size: 11.5px; font-weight: 700; letter-spacing: .03em;
    color: var(--text); border: 1px solid var(--border2);
    padding: 3px 9px; border-radius: 20px; white-space: nowrap;
  }
  .up-offer-ends.is-urgent {
    color: var(--orange); border-color: var(--orange-border); background: var(--orange-dim);
  }
  .up-tier-name { font-size: 15px; font-weight: 700; color: var(--text); }
  .up-tier-duration { font-size: 12px; color: var(--text3); margin-top: 3px; }
  .up-price { font-size: 20px; font-weight: 700; color: var(--amber); letter-spacing: -0.5px; }
  .up-price-strike { font-size: 13px; color: var(--text3); text-decoration: line-through; }
  .up-card-desc { font-size: 11.5px; color: #5DC87A; margin-top: 6px; }
  /* What the plan contains, on every card so a card stands alone. */
  .up-card-gets { font-size: 11.5px; color: var(--text3); margin-top: 8px; line-height: 1.5; }
  /* What it does to THIS buyer's dates. Sits under the buy button, quieter
     than the price but always present, so stacking is never a surprise. */
  .up-card-effect { font-size: 11px; color: var(--text3); margin-top: 8px; line-height: 1.5; }
  .up-buy-btn {
    margin-top: 14px; width: 100%; background: rgba(200,164,74,0.12);
    border: 1px solid rgba(200,164,74,0.35); border-radius: 8px; padding: 10px;
    font-size: 13px; font-weight: 700; color: var(--amber); cursor: pointer;
    letter-spacing: 0.03em; transition: background .15s, border-color .15s;
    font-family: inherit;
  }
  .up-buy-btn:hover { background: rgba(200,164,74,0.2); }
  .up-plan-card-best .up-buy-btn { background: #C8A44A; border: none; color: #070D1A; }
  .up-plan-card-best .up-buy-btn:hover { opacity: 0.88; background: #C8A44A; }
  .up-feature {
    display: flex; align-items: center; gap: 9px;
    font-size: 13px; color: var(--text3); line-height: 1.4;
  }
  .up-feature::before {
    content: ''; display: block; width: 5px; height: 5px;
    border-radius: 50%; background: #C8A44A; flex-shrink: 0;
  }
  .up-buy-btn:disabled { opacity: 0.5; cursor: not-allowed; }

  /* Upgrade modal - mobile */
  @media (max-width: 600px) {
    #upgrade-modal .up-plan-card { padding: 15px 15px 14px; }
    .up-buy-btn { min-height: 46px; }
    .up-feature { font-size: 12.5px; }
    .up-track-tab { font-size: 10.5px; padding: 8px 4px; }
  }
  @media (max-width: 360px) {
    #upgrade-modal .up-plan-card { padding: 13px; }
    .up-feature { font-size: 12px; }
  }
  /* Landscape phone: modal must scroll, never trap content off-screen */
  @media (max-height: 520px) and (orientation: landscape) {
    #upgrade-modal > div { padding-top: 14px !important; padding-bottom: 28px !important; }
    #upgrade-modal > div > div { margin-top: 0 !important; }
  }

  /* ── Touch targets ──────────────────────────────────────────────────────
     Keyed to pointer:coarse, NOT to a width breakpoint. A phone held in
     landscape is 640-950px wide - wider than any mobile breakpoint here -
     but it is still a thumb, and the max-width:600px rule above silently
     stopped applying there, dropping the pay buttons to ~37px. Measured
     before this rule: track tabs 32px, close 36px, "Have a code?" 28px,
     Apply 41px, all under the 44px minimum (WCAG 2.5.8 / Apple HIG).
     Padding is used rather than fixed height so labels never clip. */
  @media (pointer: coarse) {
    .up-track-tab      { min-height: 44px; }
    .up-buy-btn        { min-height: 46px; }
    #up-coupon-toggle  { min-height: 44px; padding: 12px 16px !important; }
    #up-coupon-btn     { min-height: 44px; }
    #up-coupon-input   { min-height: 44px; }
    /* Close buttons carry inline width/height, so they need the override. */
    #upgrade-modal .up-close-btn,
    #settings-modal .close-btn { width: 44px !important; height: 44px !important; }
  }

/* ── Hall of Fame popup (fame.js) ─────────────────────────────
   Themed on both sides of every pair: surface tokens behind, text tokens in
   front, and the accent pair uses --on-accent, since --blue and --orange
   invert between the dark and light palettes. The Sponsorship app swaps the
   accent through .hof-spon rather than a second stylesheet. */
#hof-modal { display:none; position:fixed; inset:0; z-index:10004; overflow-y:auto;
  background:rgba(4,9,20,0.93); backdrop-filter:blur(6px); --hof-acc:var(--blue);
  --hof-acc-dim:var(--blue-dim); --hof-acc-border:var(--blue-border); }
#hof-modal.hof-spon { --hof-acc:var(--orange); --hof-acc-dim:var(--orange-dim);
  --hof-acc-border:var(--orange-border); }
.hof-wrap { min-height:100%; display:flex; justify-content:center; padding:24px 16px 48px; box-sizing:border-box; }
.hof-box { width:100%; max-width:440px; margin:auto 0; background:var(--surface);
  border:1px solid var(--border); border-radius:16px; padding:26px 22px 22px; text-align:center; }
.hof-mark { width:52px; height:52px; margin:0 auto 12px; border-radius:50%; display:flex;
  align-items:center; justify-content:center; color:var(--hof-acc);
  background:var(--hof-acc-dim); border:1px solid var(--hof-acc-border); }
.hof-mark svg { width:28px; height:28px; }
.hof-title { font-family:Georgia, 'Times New Roman', serif; font-size:24px; font-weight:700;
  color:var(--text); letter-spacing:.2px; }
.hof-sub { font-size:11.5px; font-weight:700; letter-spacing:.18em; text-transform:uppercase; color:var(--hof-acc);
  line-height:1.6; margin:8px auto 18px; max-width:46ch; text-wrap:balance; }
.hof-card { display:flex; gap:14px; align-items:flex-start; text-align:left; background:var(--surface2);
  border:1px solid var(--border); border-radius:12px; padding:14px; margin-bottom:10px; }
.hof-face { flex:0 0 64px; width:64px; height:64px; border-radius:50%; object-fit:cover;
  border:2px solid var(--hof-acc-border); }
.hof-face-init { display:flex; align-items:center; justify-content:center; font-weight:700;
  font-size:20px; color:var(--hof-acc); background:var(--hof-acc-dim); box-sizing:border-box; }
.hof-who { min-width:0; flex:1; }
.hof-name { font-size:16px; font-weight:700; color:var(--text); overflow-wrap:anywhere; }
.hof-what { font-size:13.5px; color:var(--text2); margin-top:3px; line-height:1.45; }
.hof-when { font-size:11px; letter-spacing:.6px; text-transform:uppercase; color:var(--text3); margin-top:5px; }
.hof-quote { margin:10px 0 0; padding:0 0 0 10px; border-left:2px solid var(--hof-acc-border);
  font-size:13px; font-style:italic; color:var(--text2); line-height:1.55; }
.hof-btn { width:100%; min-height:46px; margin-top:8px; background:var(--hof-acc); color:var(--on-accent);
  border:none; border-radius:9px; font-size:14px; font-weight:700; cursor:pointer; font-family:inherit; }
.hof-btn:focus-visible { outline:2px solid var(--text); outline-offset:2px; }
.hof-all { display:block; margin-top:12px; font-size:13px; color:var(--text2); text-decoration:underline;
  text-underline-offset:3px; }
.hof-all:hover { color:var(--text); }
.hof-intro { font-size:14px; color:var(--text2); line-height:1.65; margin:10px auto 4px; max-width:38ch; text-wrap:pretty; }
.hof-intro[hidden] { display:none; }

/* ── Notification formatting (nf-format.js) ─────────────────────────────
   Theme tokens only. The links used to carry a fixed #7AB8E0, which is a
   light-on-light pair in the light theme; --blue is solved per theme. */
.nf-list { margin: 6px 0 6px 20px; padding: 0; }
.nf-list li { margin: 2px 0; padding-left: 2px; }
.nf-link { color: var(--blue); text-decoration: underline; text-underline-offset: 2px; word-break: break-all; }
