/* Learn shares the app's light surfaces and navy text. Topic banners keep
   their distinct colours and white labels; lesson buttons retain their depth. */
body.today-view { background: var(--paper); }
#today {
  background: var(--paper);
  border-top-color: var(--paper);
  color: var(--ink);
  padding: 0 18px calc(108px + var(--safe-area-inset-bottom, env(safe-area-inset-bottom, 0px)));
  color-scheme: light dark;
  scroll-padding-top: 220px;
  --today-status-height: 70px;
}
#today .today-inner { max-width: 540px; }
#today .sub { color: var(--ink-2); }
.today-top { position: sticky; top: 0; z-index: 4; display: flex; align-items: center; justify-content: space-between; gap: 16px; padding: 15px 0 12px; background: var(--paper); }
.today-heading { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }
.today-heading h1 { margin: 0; color: var(--ink); font-size: 22px; font-weight: 900; line-height: 1.2; letter-spacing: -.3px; }
.today-heading p { margin: 3px 0 0; color: var(--ink-2); font-size: 13px; font-weight: 600; }
.today-status { display: flex; align-items: center; justify-content: flex-end; flex: 1; gap: 14px; min-height: 44px; margin-bottom: 0; }
/* The header's stats wear the same 44px bordered control as the gear beside
   them. They were bare numbers standing next to a boxed button, which is what
   made them read as loose furniture rather than part of the row. */
.today-stat { display: flex; align-items: center; gap: 8px; height: 44px; padding: 0 12px; border: 2px solid var(--line-2); border-radius: 13px; background: var(--paper); white-space: nowrap; color: var(--ink); font-size: 15px; }
.today-stat b { font-weight: 850; font-variant-numeric: tabular-nums; }
.today-stat svg { flex: 0 0 24px; width: 24px; height: 24px; fill: currentColor; }
.today-stat small { font-size: 10px; }
/* The goal ring is a button: tap it to change the daily goal in Settings. */
/* The tick stays faint until the goal is met, so an empty ring never reads as "done". */
.today-course-topic { --topic-banner: #1cb0f6; --topic-lip: #1899d6; --topic-node: #1cb0f6; --topic-ring: #84d8ff; --topic-rest: #ddf4ff; --topic-rest-lip: #b3e5fc; --topic-icon: #1899d6; position: relative; margin-bottom: 36px; padding-bottom: 24px; }
.today-chapter-wrap { position: sticky; top: var(--today-status-height); z-index: 3; background: var(--paper); padding-bottom: 20px; }
.today-chapter { display: flex; align-items: center; justify-content: space-between; gap: 12px; min-height: 72px; padding: 12px 16px; border-radius: 16px; background: var(--topic-banner); box-shadow: 0 5px 0 var(--topic-lip); color: #fff; }
.today-chapter > div { min-width: 0; }
.today-unit { margin: 0 0 3px; color: #fff; opacity: .85; font-size: 11px; line-height: 1.4; font-weight: 900; letter-spacing: .65px; }
#today .today-chapter-title { color: #fff; margin: 0; font-size: clamp(18px, 5vw, 22px); font-weight: 900; line-height: 1.2; letter-spacing: -.35px; }
.today-path { list-style: none; margin: 0; padding: 26px 0 0; }
.today-step { display: flex; justify-content: center; min-height: 137px; }
.today-lesson { position: relative; display: flex; flex-direction: column; align-items: center; gap: 14px; width: 162px; min-height: 125px; padding: 0 0 14px; border: 0; border-radius: 16px; background: none; color: var(--ink); transform: translateX(var(--path-shift)); }
.today-lesson, .today-lesson * { -webkit-touch-callout: none; -webkit-user-select: none; user-select: none; -webkit-tap-highlight-color: transparent; }
/* The progress ring stays on the stationary wrapper; only the inner face
   compresses and springs back during a lesson press. */
/* The path's steps are rounded squares, the same shape as the mock test tiles,
   rather than the circular coins this started as. One radius drives the face,
   its inner gloss and the ring around the current step, so they cannot part
   company the way five separate 50%s could. */
.today-node-wrap { --node-radius: clamp(12px, 2vw, 16px); position: relative; display: block; flex: 0 0 65px; width: 74px; height: 65px; }
.today-node { --node-lip: var(--topic-rest-lip); --node-face: var(--topic-rest); position: relative; display: grid; place-items: center; width: 74px; height: 65px; border-radius: var(--node-radius); background: var(--topic-rest); box-shadow: 0 8px 0 var(--node-lip), inset 0 2px 0 #ffffff05; color: var(--topic-icon); transform-origin: center bottom; transition: transform .1s var(--ease), box-shadow .1s var(--ease); }
.today-node svg { width: 32px; height: 32px; fill: currentColor; }
.today-lesson-title { color: var(--ink); font-size: 12px; line-height: 1.25; font-weight: 750; max-width: 162px; text-wrap: balance; }
.is-current .today-node { --node-lip: var(--topic-lip); --node-face: var(--topic-node); background: var(--topic-node); color: #fff; box-shadow: 0 8px 0 var(--node-lip), inset 0 2px 0 #ffffff35; }
/* The active coin sits inside a thick light-grey ring, like the reference. */
.is-current .today-node-wrap::after { content: ""; position: absolute; inset: -15px -14px -21px; border: 8px solid var(--line-2); border-radius: calc(var(--node-radius) + 15px); pointer-events: none; }
.is-current .today-lesson { gap: 27px; margin-bottom: 12px; }
.today-start { position: absolute; bottom: calc(100% + 23px); left: 50%; transform: translateX(-50%); padding: 8px 14px; border: 2px solid var(--topic-rest-lip); border-radius: 10px; background: var(--paper); color: var(--topic-banner); white-space: nowrap; font-size: 13px; font-weight: 950; letter-spacing: .75px; }
/* The callout breathes, so the eye finds where to start without anything
   having to shout. Uses translate rather than transform, because the bubble is
   centred with transform: translateX(-50%) and would jump sideways otherwise. */
.today-start { animation: start-bob 1.9s ease-in-out infinite; }
@keyframes start-bob { 0%, 100% { translate: 0 0; } 50% { translate: 0 -4px; } }
.today-start::after { content: ""; position: absolute; left: calc(50% - 5px); bottom: -6px; width: 9px; height: 9px; border-right: 2px solid var(--topic-rest-lip); border-bottom: 2px solid var(--topic-rest-lip); background: var(--paper); transform: rotate(45deg); }
/* The START callout stands 65px above its coin and breathes another 4px on
   top of that, so the step has to reserve the room. With less, the callout
   overflows its own row and the sticky chapter header paints over it. */
.today-step.is-current { padding-top: 72px; }
/* Completed lessons become glossy star coins. The inset face and diagonal
   highlights travel with the pressed button; the current-step ring stays put. */
/* Completed coins keep the solid section colour and gain one soft gloss across the face; the icon is a white tick. */
.is-complete .today-node { --node-lip: var(--topic-lip); --node-face: var(--topic-node); isolation: isolate; color: #fff; background: var(--topic-node); box-shadow: 0 8px 0 var(--node-lip), inset 0 2px 0 #ffffff40; }
/* Game-app finish: a lighter inner face sits on the solid rim, and one wide
   diagonal light band crosses it from top-left to bottom-right. */
.is-complete .today-node::before { content: ""; position: absolute; inset: 5px 5px 8px; border-radius: calc(var(--node-radius) - 5px); background: color-mix(in srgb, var(--topic-node) 88%, #fff); pointer-events: none; }
.is-complete .today-node::after { content: ""; position: absolute; inset: 5px 5px 8px; border-radius: calc(var(--node-radius) - 5px); background: linear-gradient(115deg, transparent 0 40%, #ffffff40 40% 52%, transparent 52%); background-size: 250% 100%; background-position: 50% 0; pointer-events: none; transition: background-position .55s cubic-bezier(.2, .7, .2, 1); }
.is-complete .today-node svg { position: relative; z-index: 1; width: 34px; height: 34px; }
/* The permanent gloss stays in place. A separate light reflection crosses it
   during completion and disappears before the coin settles. */
.today-node-shine { position: absolute; z-index: 2; inset: 5px 5px 7px; border-radius: calc(var(--node-radius) - 5px); pointer-events: none; opacity: 0; background: linear-gradient(120deg, transparent 36%, #ffffff30 43%, #ffffffbd 49%, #ffffff75 53%, transparent 62%) 100% 50% / 250% 100% no-repeat; }
.is-celebrating .today-lesson:not(.is-pressed) .today-node { animation: lesson-finish .9s ease-in-out both; }
.is-celebrating .today-node-shine { animation: lesson-shine .9s ease-in-out both; }
.is-awaiting-reveal .today-start, .is-awaiting-reveal .today-node-wrap::after { visibility: hidden; }
.is-awaiting-reveal .today-node { background: var(--topic-rest); color: var(--topic-icon); --node-lip: var(--topic-rest-lip); --node-face: var(--topic-rest); }
.is-next-cue .today-start { animation: next-lesson-label .25s ease-out; }
.is-next-cue .today-lesson:not(.is-pressed) .today-node { animation: next-lesson-nudge 1.4s ease-in-out 3; }
@keyframes lesson-finish { 0%, 78%, 100% { transform: none; } 18% { transform: translateY(2px) scale(.97); } 42% { transform: translateY(-3px) scale(1.045); } }
@keyframes lesson-shine { 0%, 12% { background-position: 100% 50%; opacity: 0; } 28% { opacity: 1; } 68% { background-position: 0% 50%; opacity: .85; } 82%, 100% { background-position: 0% 50%; opacity: 0; } }
@keyframes next-lesson-label { from { opacity: 0; } to { opacity: 1; } }
@keyframes next-lesson-nudge { 0%, 100% { translate: 0 0; } 50% { translate: 0 -5px; } }
@media (hover: hover) and (pointer: fine) {
  /* Hover reads as a light press: the coin sinks a little into its lip. No colour change. */
  .today-lesson:hover .today-node { transform: translateY(2px); box-shadow: 0 6px 0 var(--node-lip), inset 0 2px 0 #ffffff05; }
  .is-current .today-lesson:hover .today-node, .is-complete .today-lesson:hover .today-node, .is-upcoming .today-lesson:hover .today-node { box-shadow: 0 6px 0 var(--node-lip), inset 0 2px 0 #ffffff35; }
  /* The reflection reacts to the mouse: the band glides across the face and settles back on leave. */
  .is-complete .today-lesson:hover .today-node::after { background-position: 12% 0; }
}
/* A press, not a squash. The face sinks the full depth of its lip and the
   lip closes to match, so the bottom edge never moves. */
.today-step .today-lesson.is-pressed .today-node { transform: translateY(6px); box-shadow: 0 2px 0 var(--node-lip), inset 0 2px 0 #ffffff20; }
.today-lesson:focus-visible { outline: 2px solid var(--brand-ink); outline-offset: 5px; }
.today-lesson-title b, .today-lesson-title small { display: block; color: var(--ink); }
.today-lesson-title b { font-size: 14px; font-weight: 900; }
.today-lesson-title small { color: var(--ink-2); font-size: 12px; font-weight: 650; margin-top: 4px; }
/* Every lesson coin is a solid block of its section colour; the current one adds the ring and label. */
/* Everything still ahead of you sits grey, so the colour is an invitation
   rather than wallpaper: where you are now, and the first step of each group —
   somewhere to start if you would rather not pick up where you left off. */
.is-upcoming .today-node { --node-lip: var(--disabled); --node-face: var(--panel-2); background: var(--panel-2); color: var(--ink-3); box-shadow: 0 8px 0 var(--node-lip), inset 0 2px 0 #ffffff55; }
.is-upcoming.is-entry .today-node { --node-lip: var(--topic-lip); --node-face: var(--topic-node); background: var(--topic-node); color: #fff; box-shadow: 0 8px 0 var(--node-lip), inset 0 2px 0 #ffffff35; }
.is-upcoming:not(.is-entry) .today-guided-kind { color: var(--ink-3); }
.today-load-notice { padding: 16px; margin-bottom: 20px; border: 1px solid var(--brand-line); border-radius: 16px; }
.today-load-notice p { color: var(--ink-2); }
.today-load-notice button { color: var(--brand-ink); }
.today-extras { display: grid; gap: 10px; margin: 0 auto; max-width: 380px; }
.today-extras button { display: flex; align-items: center; gap: 13px; width: 100%; min-height: 78px; padding: 13px 16px; border: 2px solid var(--line-2); border-radius: 16px; background: var(--panel); color: var(--ink); text-align: left; }
.today-extra-icon { display: grid; place-items: center; width: 38px; height: 38px; color: var(--brand-ink); }
.today-extra-icon svg { width: 29px; height: 29px; fill: currentColor; }
.today-extras button > span:nth-child(2) { flex: 1; }
.today-extras b, .today-extras small { display: block; color: var(--ink); }
.today-extras b { font-size: 16px; font-weight: 900; }
.today-extras small { color: var(--ink-2); margin-top: 3px; font-size: 12px; font-weight: 600; }
.today-extras button > span:last-child { font-size: 30px; }
#today .big { color: #fff; background: #1cb0f6; }
@media (max-width: 359px) {
  #today { padding-left: 14px; padding-right: 14px; }
  .today-status { gap: 8px; }
  .today-stat { gap: 6px; padding: 0 10px; font-size: 14px; }
  .today-chapter { gap: 8px; padding-left: 14px; padding-right: 14px; }
  .today-unit { font-size: 11px; }
  .today-lesson { transform: translateX(calc(var(--path-shift) * .8)); }
}
@media (min-width: 960px) {
  #today .today-heading h1 { font-size: 24px; }
  /* Game-app top: the heading stays for screen readers only, the stats
     sit as a plain right-aligned row, and the section banner is the real header. */
  .today-status { justify-content: flex-end; gap: 10px; min-height: 44px; }
  .today-stat { gap: 8px; font-size: 15px; }
  .today-chapter { min-height: 76px; padding: 14px 22px; }
  #today .today-chapter-title { font-size: 23px; }
  .today-step { min-height: 152px; }
  .today-node-wrap { flex-basis: 74px; width: 84px; height: 74px; }
  .today-node { width: 84px; height: 74px; }
  .today-node svg { width: 36px; height: 36px; }
  .is-complete .today-node svg { width: 38px; height: 38px; }
  .today-lesson-title b { font-size: 15px; }
  /* Specificity beats the base rules declared after this block. */
  #today .today-group-notes { display: inline-flex; align-items: center; width: auto; height: 40px; gap: 6px; padding: 0 14px 0 10px; font-size: 13px; font-weight: 800; }
  #today .today-group-notes .today-notes-label { display: inline; }
}
/* The path eases up into place whenever it is shown, including on return from a lesson. */
.today-inner.today-enter { animation: today-enter .36s cubic-bezier(.2, .7, .2, 1) both; }
@keyframes today-enter { from { opacity: 0; transform: translateY(18px); } to { opacity: 1; transform: none; } }
@media (prefers-reduced-motion: reduce) {
  .today-inner.today-enter { animation: none; }
  .is-complete .today-node::after { transition: none; }
  .today-node { transition: none; }
  .is-celebrating .today-lesson:not(.is-pressed) .today-node, .is-celebrating .today-node-shine, .today-start, .is-next-cue .today-start, .is-next-cue .today-lesson:not(.is-pressed) .today-node { animation: none; }
  .today-step .today-lesson.is-pressed .today-node { transform: none; filter: brightness(.92); }
}

/* Review sits above the path: yesterday's misses, before today's new ground. */
/* The cream fill was a literal while the text took --ink, so in dark mode the
   card kept its light background and the heading turned near-white on it —
   about 1.0:1, a word you could only make out from its letter shapes. The
   amber tokens already carry both themes. */
.today-review { display: flex; align-items: center; gap: 14px; width: 100%; margin: 0 0 24px; padding: 14px 16px; border: 2px solid var(--amber-line); border-radius: 18px; background: var(--amber-soft); color: var(--ink); text-align: left; box-shadow: 0 3px 0 var(--amber-line); }
.today-review:active { transform: translateY(2px); box-shadow: 0 1px 0 var(--amber-line); }
.today-review-icon { display: grid; place-items: center; flex: 0 0 44px; width: 44px; height: 44px; border-radius: 50%; background: #ff9600; color: #fff; }
.today-review-icon svg { width: 24px; height: 24px; fill: none; stroke: currentColor; stroke-width: 2.6; stroke-linecap: round; stroke-linejoin: round; }
.today-review-copy { flex: 1; min-width: 0; }
.today-review-copy b { display: block; font-size: 16px; font-weight: 900; }
.today-review-copy small { display: block; margin-top: 2px; color: var(--ink-2); font-size: 13px; font-weight: 700; }
.today-review-go { color: var(--ink-2); font-size: 24px; }

/* The five syllabus sections keep their colour through every group and coin. */
/* Section palette: five saturated hues with strongly darker lips, so coins and
   banners read as bright, pressable game pieces. */
[data-section="values"] { --topic-banner: #1cb0f6; --topic-lip: #1899d6; --topic-node: #1cb0f6; --topic-ring: #84d8ff; --topic-rest: #ddf4ff; --topic-rest-lip: #b3e5fc; --topic-icon: #1899d6; }
[data-section="uk"] { --topic-banner: #58cc02; --topic-lip: #46a302; --topic-node: #58cc02; --topic-ring: #b5ec78; --topic-rest: #e6f8d6; --topic-rest-lip: #c1eb9d; --topic-icon: #46a302; }
[data-section="history"] { --topic-banner: #ff9600; --topic-lip: #cc7800; --topic-node: #ff9600; --topic-ring: #ffd08a; --topic-rest: #fff1dc; --topic-rest-lip: #ffd9a6; --topic-icon: #cc7800; }
[data-section="society"] { --topic-banner: #ff5fae; --topic-lip: #d94590; --topic-node: #ff5fae; --topic-ring: #ffb3d9; --topic-rest: #ffe6f2; --topic-rest-lip: #ffc4e0; --topic-icon: #d94590; }
[data-section="government"] { --topic-banner: #b26ff5; --topic-lip: #9052d6; --topic-node: #ce82ff; --topic-ring: #e2c0ff; --topic-rest: #f3e8ff; --topic-rest-lip: #e0c8ff; --topic-icon: #9052d6; }
/* The section hues stay saturated in dark — banners, coins and rings read on
   either ground. What cannot survive is --topic-rest and --topic-rest-lip: they
   are the pale resting surface of every not-yet-started coin and its 8px lip,
   so left alone they would be five bright pastel blobs on a dark path. Each
   becomes a deep tint of its own hue, keeping the section colour-coding. */
@media (prefers-color-scheme: dark) {
  .today-course-topic { --topic-rest: #0e2b3d; --topic-rest-lip: #08202f; }
  [data-section="values"] { --topic-rest: #0e2b3d; --topic-rest-lip: #08202f; }
  [data-section="uk"] { --topic-rest: #16290a; --topic-rest-lip: #101e07; }
  [data-section="history"] { --topic-rest: #2e1f08; --topic-rest-lip: #221605; }
  [data-section="society"] { --topic-rest: #2e1122; --topic-rest-lip: #220c19; }
  [data-section="government"] { --topic-rest: #241a33; --topic-rest-lip: #1a1226; }
}
.today-path-group + .today-path-group { margin-top: 22px; }
.today-group-heading { display: flex; align-items: center; gap: 12px; min-height: 48px; padding: 0 10px; }
.today-group-heading::after { content: ""; flex: 1; height: 2px; background: var(--topic-rest); }
#today .today-group-heading h3 { color: var(--ink-2); font-size: 15px; line-height: 1.35; font-weight: 750; margin: 0; }
.today-group-notes { display: grid; place-items: center; order: 1; flex: 0 0 44px; width: 44px; height: 44px; padding: 10px; border: 0; border-radius: 12px; color: var(--topic-banner); background: var(--topic-rest); }
.today-group-notes svg { width: 24px; height: 24px; fill: currentColor; }
.today-notes-label { display: none; }
.today-section-empty { margin: 12px 16px 32px; color: var(--ink-2); font-size: 15px; line-height: 1.5; }
/* Steps behind the paywall: a flat slate coin with its own icon greyed, the
   same slate the locked mock tiles wear, so "not yours yet" reads the same
   everywhere. */
.is-locked .today-node { --node-lip: #97a6b6; --node-face: #b9c5d1; background: #b9c5d1; color: #46566a; box-shadow: 0 8px 0 var(--node-lip), inset 0 2px 0 #ffffff35; }
.is-locked .today-lesson-title b { color: var(--ink-2); }
