/* ui-academy: the Academy's intro card, its coach marks (spotlight ring and card) and the sheets after a lesson (why it worked, teach-back, reward). Tokens come from styles.css. */

/* ---- intro */
.ac-intro { max-width: 46rem; margin: clamp(1rem, 12vh, 6rem) auto 3vh; display: grid; gap: .6rem; border-top: 6px solid var(--gold); background: linear-gradient(180deg, color-mix(in srgb, var(--gold) 8%, var(--panel)), var(--panel) 9rem); }
.ac-eyebrow { margin: 0; font-size: .72rem; text-transform: uppercase; letter-spacing: .1em; color: var(--gold); }
.ac-head { display: flex; align-items: center; justify-content: space-between; gap: .6rem; margin-bottom: .1rem; }
.ac-dots { display: inline-flex; gap: .25rem; flex: none; } .ac-dots i { width: .5rem; height: .5rem; border: 1px solid var(--gold); border-radius: 50%; } .ac-dots i.on { background: var(--gold); }
.ac-intro h1 { display: flex; align-items: center; gap: .75rem; margin: 0; font-size: clamp(1.5rem, 4vw, 2.2rem); color: var(--gold); text-shadow: 3px 3px 0 #000; overflow-wrap: anywhere; }
/* the lesson's emblem is a framed tile of its own, the first thing the eye lands on: the one object on an otherwise quiet card */
.ac-intro h1 > span[aria-hidden="true"] { display: inline-grid; place-items: center; flex: none; width: 3.5rem; height: 3.5rem; font-size: 2.15rem; line-height: 1; text-shadow: 0 0 1px rgba(255, 255, 255, .85), 0 0 2px rgba(255, 255, 255, .3);
  background: radial-gradient(circle at 50% 38%, color-mix(in srgb, var(--gold) 22%, var(--bg)), var(--bg) 78%); border: 2px solid var(--gold); border-radius: 10px; box-shadow: 3px 3px 0 rgba(0, 0, 0, .55); }
.ac-intro h1:focus, .ac-sheet h2:focus { outline: none; }
.ac-scene { font-size: 1.05rem; border-left: 4px solid var(--cyan); padding: .55rem .95rem; background: var(--info-bg); margin: .3rem 0; line-height: 1.5; }
.ac-facts { list-style: none; padding: 0; margin: 0; display: flex; gap: .4rem; flex-wrap: wrap; }
.ac-pips { list-style: none; display: flex; gap: .45rem; padding: 0; margin: .5rem 0; flex-wrap: wrap; }
.ac-pip { position: relative; width: 2.1rem; height: 2.1rem; display: grid; place-items: center; border: var(--bw) solid var(--line); font-family: ui-monospace, Menlo, monospace; font-size: .8rem; color: var(--mute); border-radius: 2px; }
.ac-pip + .ac-pip::before { content: ""; position: absolute; right: 100%; top: 50%; width: .45rem; border-top: 2px solid var(--line); }
.ac-pip.done { border-color: var(--green); color: var(--green); background: var(--good-bg); }
.ac-pip.done + .ac-pip::before { border-top-color: var(--green); }
.ac-pip.skipped { border-color: var(--gold); color: var(--gold); }
.ac-pip.now { border-color: var(--gold); background: var(--gold); color: var(--on-gold); font-weight: 700; }

/* ---- coach marks: a ring round the real control, a card beside it. The layer lets every click through except the card's own. */
.ac-layer, .overlay > .ac-layer { position: fixed; inset: 0; z-index: 30; pointer-events: none; }
.ac-ring { position: fixed; left: 0; top: 0; border: 3px solid var(--gold); border-radius: 8px; pointer-events: none; will-change: transform;
  box-shadow: 0 0 0 100vmax rgba(5, 8, 14, .55), 0 0 0 1px rgba(5, 8, 14, .85), 0 0 16px 2px var(--gold); transition: transform .25s ease, width .25s ease, height .25s ease; animation: ac-pulse 1.8s ease-in-out infinite; }
.ac-ring.show { border-width: 5px; border-color: var(--focus); animation: ac-show .9s ease-in-out infinite; }
@keyframes ac-pulse { 0%, 100% { box-shadow: 0 0 0 100vmax rgba(5, 8, 14, .55), 0 0 0 1px rgba(5, 8, 14, .85), 0 0 0 0 rgba(255, 194, 71, .7); } 50% { box-shadow: 0 0 0 100vmax rgba(5, 8, 14, .55), 0 0 0 1px rgba(5, 8, 14, .85), 0 0 0 12px rgba(255, 194, 71, 0); } }
@keyframes ac-show { 0%, 100% { box-shadow: 0 0 0 100vmax rgba(5, 8, 14, .66), 0 0 0 1px rgba(5, 8, 14, .85), 0 0 0 0 rgba(255, 242, 122, .9); } 50% { box-shadow: 0 0 0 100vmax rgba(5, 8, 14, .66), 0 0 0 1px rgba(5, 8, 14, .85), 0 0 0 18px rgba(255, 242, 122, 0); } }
/* The card is a frame that never clips: the caret on its edge sticks out past the border, so the frame has overflow visible and the words scroll in .ac-coach-in. */
.ac-coach { position: fixed; left: 0; top: 0; width: min(21.5rem, calc(100vw - 1rem)); background: var(--panel); background: linear-gradient(180deg, var(--ac-top), var(--panel) 3.4rem); border: var(--bw) solid var(--gold); border-radius: 4px; box-shadow: 0 0 0 1px var(--bg), 6px 6px 0 rgba(0, 0, 0, .55), 0 14px 34px rgba(0, 0, 0, .5); pointer-events: auto; transition: transform .25s ease; --ac-top: color-mix(in srgb, var(--gold) 10%, var(--panel)); }
.ac-coach-in { max-height: calc(100vh - 1rem); max-height: calc(100dvh - 1rem); overflow: auto; padding: .7rem .9rem .8rem; border-radius: 2px; }
.ac-coach:focus { outline: none; }
/* The card's sizes (js/ui/academy-sandbox.js, chooseSize): the whole card; `slim`, the step's words, the hint once it is due and the buttons, without the notes under the words (a window's buttons are in the way of the
   whole card); `narrow`, slim in a column 15rem wide. Every one of them says what the step says and has every button: a shape that dropped the words left a player who is stuck with a card that told them nothing,
   so there is none. Where none stands clear of the controls the card is its tab (below), which stands in a place of its own. */
.ac-coach.slim :is(.ac-look, .ac-where) { display: none; }
/* handle (js/ui/academy.js): where no size of the card stands clear of the controls, the card folds to a one-line tab that opens it. The words and the hint stay in the page, clipped and not display: none, so a screen reader still has them. */
.ac-coach.narrow { width: min(15rem, calc(100vw - 1rem)); } /* slim in a column: a phone on its side has an empty one beside the buttons */
.ac-coach.wide { width: min(46rem, calc(100vw - 1rem)); } /* the card the player opened, where the full one is taller than the window: the same words across the strip's width (`wide slim` drops the notes too) */
.ac-grab { display: none; }
.ac-coach.handle { width: max-content; max-width: calc(100vw - 1rem); }
.ac-coach.handle[data-side]::before { display: none; } /* one more attribute than the caret's own rules below (.ac-coach[data-side="below"]::before), so the tab has no caret and nothing is forced */
.ac-coach.handle .ac-coach-in { padding: 0; max-height: none; overflow: visible; }
.ac-coach.handle :is(.ac-head, .ac-btns) { display: none; }
.ac-coach.handle :is(.ac-say, .ac-hint, .ac-look, .ac-where, .ac-lost) { position: absolute; width: 1px; height: 1px; margin: -1px; padding: 0; border: 0; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }
.ac-coach.handle .ac-grab { display: flex; align-items: center; gap: .45rem; min-height: 2.5rem; padding: .3rem .7rem; border: 0; border-radius: 2px; background: transparent; color: var(--gold); font: inherit; font-size: .74rem; font-weight: 700; text-transform: uppercase; letter-spacing: .08em; white-space: nowrap; cursor: pointer; }
.ac-coach.handle .ac-grab::after { content: "\25B8"; }
.ac-grab .ac-gt { display: none; } .ac-grab .ac-gl { font-weight: 700; }
/* in the strip the tab has the strip's width and says what the step says, in one line: a player who is stuck reads the gist, or the hint, without a tap, and a tap opens the whole card */
.ac-coach.handle.instrip { width: min(calc(100vw - 1rem), 46rem); }
.ac-coach.handle.instrip .ac-grab { width: 100%; }
.ac-coach.handle.instrip .ac-gt { display: block; flex: 1 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-weight: 400; text-transform: none; letter-spacing: 0; color: var(--ink); font-size: .88rem; }
.ac-coach.handle.instrip .ac-grab::after { margin-left: auto; }
.ac-coach.handle .ac-grab:hover { background: color-mix(in srgb, var(--gold) 14%, transparent); }
/* the caret is a turned square that carries the card's own colour at the edge it sits on (the lit top for "below", the plain panel elsewhere), so it joins the frame without a seam */
.ac-coach::before { content: ""; position: absolute; display: none; width: 12px; height: 12px; background: var(--panel); border: var(--bw) solid var(--gold); transform: rotate(45deg); }
.ac-coach[data-side="below"]::before { display: block; top: -8px; left: clamp(1.1rem, var(--ac-ax, 50%), calc(100% - 1.5rem)); margin-left: -6px; border-right: 0; border-bottom: 0; background: var(--ac-top); }
.ac-coach[data-side="above"]::before { display: block; bottom: -8px; left: clamp(1.1rem, var(--ac-ax, 50%), calc(100% - 1.5rem)); margin-left: -6px; border-left: 0; border-top: 0; }
.ac-coach[data-side="right"]::before { display: block; left: -8px; top: clamp(1.1rem, var(--ac-ay, 50%), calc(100% - 1.5rem)); margin-top: -6px; border-right: 0; border-top: 0; }
.ac-coach[data-side="left"]::before { display: block; right: -8px; top: clamp(1.1rem, var(--ac-ay, 50%), calc(100% - 1.5rem)); margin-top: -6px; border-left: 0; border-bottom: 0; }
.ac-coach .ac-say { margin: .3rem 0 .6rem; font-size: .96rem; line-height: 1.5; }
.ac-coach .ac-hint, .ac-coach .ac-look { margin: .3rem 0 .6rem; font-size: .84rem; padding: .35rem .55rem; background: var(--warn-bg); border-left: 4px solid var(--gold); }
/* a thing the card cannot frame (not on screen yet, or under a window): what to do to bring it up, in the info colors so it is not mistaken for the hint */
.ac-coach .ac-where { margin: .3rem 0 .6rem; font-size: .84rem; padding: .35rem .55rem; background: var(--info-bg); border-left: 4px solid var(--cyan); }
/* a lesson that can no longer be finished: the card is calm (it is nobody's fault) and its one primary button is Restart */
.ac-coach .ac-lost { margin: .3rem 0 .6rem; font-size: .84rem; color: var(--mute); }
.ac-coach.stranded .ac-say { font-weight: 700; }
.ac-btns { display: flex; flex-wrap: wrap; gap: .4rem; }
/* The card's words scroll in .ac-coach-in when the window is shorter than they are (the full card with its hint is 378px of a 390px window), and the buttons are the last thing in them: they stay at the foot of the
   part that scrolls while the words go by above them, so Show me, Skip lesson and Restart are never cut by the card's own scroll. Nothing here changes the card's size: where the words fit, the row is where it
   always was (the sticky edge is the box of the words, so the card's padding stays under it), and the shadow, which has no size, paints the strip of that padding the words would otherwise show through. */
.ac-coach:not(.handle) .ac-btns { position: sticky; bottom: 0; z-index: 1; background: var(--panel); box-shadow: 0 .8rem 0 0 var(--panel); }
/* a toast the card stands over (js/ui/academy.js, toastsYield): the card's words outrank it, and it is read out anyway. Its own opacity transition (styles.css) does the fade. */
.toast.ac-under { opacity: 0; }
.ac-btns .btn[aria-pressed="true"] { border-color: var(--gold); color: var(--gold); }

/* ---- the strip: the card's own place in a small window. A tab has to stand somewhere that no control is, and in a window that is short or narrow (js/ui/academy-sandbox.js, smallWindow: under 44rem high or 46rem wide, in
   the page's own rem) the layout keeps a strip along the bottom edge for it, for as long as a lesson is on screen: the gutter under the dock (--edge-b) is that much deeper, so the dock, the drawer, the ticker and the toasts all
   stand above it, and a window (a <dialog>: the Deal Room, the hire dialog, the Cash breakdown, an alert) ends above it. The card is a floating card where a clear place exists and its tab in the strip where none does,
   and nothing else can ever be under the tab. A large window has no strip (a clear place for the tab is always there) and its layout is the one it always was. */
:root { --ac-strip: calc(var(--target) + var(--sp-3)); }
html.ac-strip { --edge-b: calc(max(var(--sp-2), env(safe-area-inset-bottom, 0px)) + var(--ac-strip)); }
html.ac-strip dialog#dlg { inset-block-end: var(--ac-strip); } /* its max-height is already 100dvh less --edge-t and --edge-b, and --edge-b has the strip in it */
html.ac-strip dialog#dlg.deal { max-height: calc(100vh - var(--ac-strip) - .5rem); max-height: calc(100dvh - var(--ac-strip) - .5rem); }
@media (max-width: 760px) { html.ac-strip dialog#dlg.deal { height: calc(100vh - var(--ac-strip)); height: calc(100dvh - var(--ac-strip)); max-height: calc(100vh - var(--ac-strip)); max-height: calc(100dvh - var(--ac-strip)); } }
.ac-stripbox { position: fixed; left: 0; right: 0; bottom: 0; height: var(--ac-strip); visibility: hidden; pointer-events: none; } /* measured, never seen: how tall the strip is, in pixels, for the tab to be centred in it */

/* A short window (a phone on its side, a laptop at 200%) has the card's own padding and the gaps between its parts tightened, so the words, the notes, the hint and the buttons fit the window at a large text size too. */
@media (max-height: 520px) {
  .ac-coach-in { padding: .5rem .8rem .6rem; }
  .ac-coach .ac-say { margin: .2rem 0 .4rem; }
  .ac-coach .ac-hint, .ac-coach .ac-look, .ac-coach .ac-where, .ac-coach .ac-lost { margin: .2rem 0 .4rem; padding: .25rem .5rem; }
}
/* While the strip is reserved the camera and list buttons (placed from the top, under the tracker) end above it, however tall the tracker is: the strip is the tab's, and nothing else may stand in it. */
html.ac-strip .worldhost { --cam-top: min(max(calc(50% - var(--cam-h) / 2), calc(var(--trk-b) + var(--sp-2))), calc(100% - var(--edge-b) - var(--cam-h) - var(--sp-2) - var(--target))); }

/* ---- the sheets after a win */
.ac-sheet { position: fixed; inset: 0; z-index: 40; background: rgba(5, 8, 14, .8); display: grid; justify-items: center; align-items: start; overflow: auto; padding: 4vh .8rem; scroll-padding-block: .5rem; }
.ac-sheet-in { width: min(44rem, 100%); background: var(--panel); border: var(--bw) solid var(--gold); border-top-width: 6px; box-shadow: 8px 8px 0 rgba(0, 0, 0, .6); padding: 1.1rem 1.3rem 1.3rem; display: grid; gap: .5rem; min-width: 0; animation: ac-rise .26s cubic-bezier(.2, .9, .3, 1) both; }
@keyframes ac-rise { from { opacity: 0; transform: translateY(12px); } to { opacity: 1; transform: none; } }
.ac-sheet-in h2 { margin: 0; overflow-wrap: anywhere; } .ac-sheet-in h3 { margin: .6rem 0 .2rem; } .ac-sheet-in p { margin: .25rem 0; overflow-wrap: anywhere; }
.ac-formula { background: var(--bg); border: 1px solid var(--line); border-left: 4px solid var(--cyan); padding: .6rem .8rem; white-space: pre-wrap; overflow-x: auto; color: var(--cyan); margin: .4rem 0; font-size: .92rem; }
.ac-ex { background: var(--panel2); border: 1px solid var(--line); padding: .6rem .9rem; margin: .4rem 0; }
.ac-ex h3 { margin-top: 0; font-size: .78rem; text-transform: uppercase; letter-spacing: .08em; color: var(--mute); } .ac-ex ol { margin: .3rem 0; padding-left: 1.3rem; } .ac-ex li { margin: .2rem 0; }
.ac-ex ol { list-style: none; padding-left: 0; counter-reset: acs; } .ac-ex ol li { counter-increment: acs; display: grid; grid-template-columns: 1.6rem minmax(0, 1fr); gap: .5rem; align-items: start; }
.ac-ex ol li::before { content: counter(acs); display: grid; place-items: center; width: 1.4rem; height: 1.4rem; border: 1px solid var(--cyan); border-radius: 50%; color: var(--cyan); font: 700 .72rem ui-monospace, Menlo, monospace; }
.ac-result { margin-top: .5rem; padding-top: .4rem; border-top: 1px dashed var(--line); }

/* teach-back: three large options, a reason under every one you pick */
.ac-opts { list-style: none; padding: 0; margin: .4rem 0; display: grid; gap: .6rem; }
.ac-opt { width: 100%; text-align: left; display: grid; grid-template-columns: 2.1rem 1fr; gap: .7rem; align-items: center; min-height: 3.4rem; padding: .7rem .9rem; background: var(--panel2); color: var(--ink); border: var(--bw) solid var(--field); font: inherit; font-size: 1rem; cursor: pointer; border-radius: 2px; }
.ac-opt:hover:not([aria-disabled="true"]) { border-color: var(--gold); }
.ac-opt[aria-disabled="true"] { cursor: default; }
.ac-opt.wrong { border-color: var(--red); background: var(--bad-bg); } .ac-opt.right { border-color: var(--green); background: var(--good-bg); }
.ac-k { display: grid; place-items: center; width: 2rem; height: 2rem; border: var(--bw) solid currentColor; font-family: ui-monospace, Menlo, monospace; font-weight: 700; border-radius: 2px; }
.ac-why { margin: .3rem 0 0 .2rem; padding: .35rem .7rem; border-left: 4px solid var(--line); font-size: .9rem; }
.ac-why.good { border-color: var(--green); } .ac-why.bad { border-color: var(--red); }
.ac-fb { min-height: 1px; }

/* reward */
.ac-rw { list-style: none; padding: 0; margin: .3rem 0; display: flex; gap: .6rem; flex-wrap: wrap; font-size: 1.1rem; }
.ac-rw .chip { padding: .3rem .9rem; border-width: 2px; background: var(--good-bg); font: 700 1.1rem ui-monospace, Menlo, monospace; animation: ac-rise .4s .15s cubic-bezier(.2, 1.4, .4, 1) both; } .ac-rw .chip + .chip { animation-delay: .3s; }
.ac-cx { list-style: none; padding: 0; margin: .3rem 0; display: grid; gap: .5rem; }
.ac-cxcard { border-left: 4px solid var(--cyan); display: grid; grid-template-columns: 2.4rem 1fr; gap: .6rem; align-items: start; padding: .5rem .7rem; background: var(--panel2); border: 1px solid var(--line); }
.ac-cxi { font-size: 1.6rem; text-align: center; line-height: 1.2; } .ac-cxcard p { margin: .1rem 0 0; }

/* A phone on its side is 390px tall or less: the card is tightened (a smaller emblem and title, a shorter scene, the ten step markers on one line) until "Start the lesson"
   is on the first screen, as it is in a taller window. */
@media (max-height: 520px) {
  .ac-intro { margin: .5rem auto; gap: .35rem; padding-block: .7rem; }
  .ac-intro h1 { gap: .55rem; font-size: 1.3rem; }
  .ac-intro h1 > span[aria-hidden="true"] { width: 2.5rem; height: 2.5rem; font-size: 1.5rem; border-radius: 8px; }
  .ac-scene { margin: 0; padding: .3rem .8rem; font-size: .92rem; line-height: 1.4; }
  .ac-pips { flex-wrap: nowrap; gap: .3rem; margin: .1rem 0; }
  .ac-pip { flex: 1 1 0; min-width: 0; max-width: 1.8rem; width: auto; height: 1.6rem; font-size: .72rem; }
  .ac-pip + .ac-pip::before { width: .3rem; }
  .ac-intro > .row { gap: .5rem; }
  .ac-intro > .row .btn { min-height: 2.6rem; }
}
/* The card is as tall as its words, up to the window (.ac-coach-in above): a cap of a third or a half of the window cut the hint and the buttons off in a short one, and a card that scrolls inside itself shows a stuck player
   half of what it says. js/ui/academy.js asks each size whether its words fit (`cut`), so a size whose words would scroll is not taken: the next one is, and then the tab. */
@media (max-width: 760px) {
  .ac-coach { width: calc(100vw - 1rem); }
  .ac-sheet { padding: 1vh .4rem; } .ac-sheet-in { padding: .8rem .85rem 1rem; }
}
@media (prefers-reduced-motion: reduce) { .ac-ring, .ac-ring.show, .ac-sheet-in, .ac-rw .chip { animation: none; } .ac-ring, .ac-coach { transition: none; } }
:root[data-motion="reduce"] .ac-ring, :root[data-motion="reduce"] .ac-ring.show, :root[data-motion="reduce"] .ac-sheet-in, :root[data-motion="reduce"] .ac-rw .chip { animation: none; }
:root[data-motion="reduce"] .ac-ring, :root[data-motion="reduce"] .ac-coach { transition: none; }
:root[data-contrast="high"] .ac-ring { box-shadow: 0 0 0 100vmax rgba(0, 0, 0, .7); }
