/* Deva Game — served from /devagame-assets/game.css, outside WordPress's
   content pipeline entirely. Palette follows the splash and
   import/design-tokens.json: deep purple ground, gold accent, cream text. */

:root {
  --ink:      #f4efe4;
  --ink-dim:  #b9b0c8;
  --ground:   #1c1530;
  --raised:   #2b2046;
  --edge:     #43356b;
  --gold:     #dcc151;
  --green:    #7fb884;
  /* Brand colours, from import/design-tokens.json and the mark itself.
     The purple is lifted from the brand #66708d: at #66708d on this dark
     ground the title sits at 3.6:1, which only passes as large text, and a
     masthead should not depend on being large enough. */
  --brand-purple: #8b93b8;
  --brand-green:  #6fa774;
  --red:      #e08a7a;
  --serif:    "Gentium Plus", Georgia, serif;
  --deva:     "Noto Sans Devanagari", "Noto Serif Devanagari", serif;
  --col:      36rem;
  --footh:    3.6rem;   /* footer height, so overlays can clear it */
  --dockh:    34vh;     /* docked chart height, cycled by the \u21d5 button */
  /* The phone's own edges: the status bar / notch on top, the home bar at
     the bottom (zero on a desktop). Everything reads these two, so a test
     can set them to an iPhone's and see what an iPhone shows. */
  --sat:      env(safe-area-inset-top, 0px);
  --sab:      env(safe-area-inset-bottom, 0px);
  /* The height a game really has: the visible screen (dvh follows Safari's
     toolbars) less the phone's own edges. Games size to this, never 100vh. */
  --vh:       100vh;
  --play:     calc(var(--vh) - var(--sat) - var(--sab));
}
@supports (height: 100dvh) { :root { --vh: 100dvh; } }

* { box-sizing: border-box; }

html, body {
  margin: 0; padding: 0;
  background: var(--ground);
  color: var(--ink);
  font-family: var(--serif);
  font-size: 17px;
  line-height: 1.5;
  -webkit-text-size-adjust: 100%;
}

#dg-app {
  max-width: var(--col);
  margin: 0 auto;
  /* Clear of the status bar when the app runs full screen from the home screen. */
  padding: calc(1.25rem + var(--sat)) 1rem calc(5.5rem + var(--sab));
  min-height: 100vh;
}

h1, h2, h3 { font-weight: 700; letter-spacing: .01em; margin: 0 0 .5rem; }
h1 { font-size: 1.5rem; }
h2 { font-size: 1.2rem; }
p  { margin: 0 0 .75rem; }
a  { color: var(--gold); }
/* A button that goes somewhere inside the app, dressed as the links beside
   it. It is a button and not a link because there is no url to give it -
   the destination is a view, not a page - and a link with no href is the
   kind of thing that works with a mouse and not with a keyboard. */
.dg-linkbtn {
  padding: 0; border: 0; background: transparent;
  color: var(--gold); font: inherit; text-align: left;
  text-decoration: underline; text-underline-offset: 2px;
  cursor: pointer; touch-action: manipulation;
}
@media (hover: hover) { .dg-linkbtn:hover { color: var(--ink); } }

.dg-quiet { color: var(--ink-dim); font-size: .92rem; }
.dg-gold  { color: var(--gold); }
.dg-center { text-align: center; }

/* ---------------------------------------------------------- masthead */

/* Mark and wordmark sit together at the left. space-between belonged to the
   older masthead, where the logo was on the far right; with both on the same
   side it just pushed the title across an empty gap. */
.dg-head {
  display: flex; align-items: center; justify-content: flex-start;
  gap: .6rem; margin-bottom: 1.25rem;
  border-bottom: 1px solid var(--edge); padding-bottom: .6rem;
}
/* The mark and the name are one button now. It has to look exactly like
   the masthead it replaced - no border, no background, no button padding -
   while still being a real button underneath, which is what keeps it
   reachable by keyboard and announced as something you can press. */
.dg-homebtn {
  display: flex; align-items: center; gap: .6rem;
  padding: 0; margin: 0; border: 0; background: transparent;
  color: inherit; font: inherit; text-align: left;
  touch-action: manipulation; cursor: pointer;
}
.dg-homebtn:focus-visible { outline: 2px solid var(--gold); outline-offset: 3px; border-radius: .3rem; }
@media (hover: hover) { .dg-homebtn:hover .dg-t-game { color: var(--gold); } }
.dg-headtext { min-width: 0; }
.dg-head .dg-title { font-size: 1.3rem; font-weight: 700; letter-spacing: .01em; }
.dg-t-deva { color: var(--brand-purple); }
.dg-t-game { color: var(--brand-green); }
/* Same size as the footer's mark, so one brand mark at one size. */
.dg-mark {
  height: 1.9rem !important; width: 1.9rem !important;
  flex: 0 0 auto; display: block;
}
/* Out at the right of the header rather than under the name. */
.dg-score {
  font-variant-numeric: tabular-nums; color: var(--ink-dim); font-size: .9rem;
  margin-left: auto; flex: 0 0 auto; white-space: nowrap;
}

/* ------------------------------------------------------------ buttons */

button {
  font-family: inherit; font-size: 1rem; color: inherit;
  background: var(--raised); border: 1px solid var(--edge);
  border-radius: .5rem; padding: .7rem .9rem; cursor: pointer;
  transition: border-color .12s ease, background .12s ease;
}
/*
 * Hover only where hovering is a thing.
 *
 * A touch screen has no hover, so a browser fakes one on tap and leaves it
 * stuck to whatever you last touched until you touch something else. That
 * left the gold hover border on a button you had just UNticked, reading as
 * if it were still on. Every hover rule in this file is behind this query
 * for the same reason.
 */
@media (hover: hover) { button:hover:not(:disabled) { border-color: var(--gold); } }
button:focus-visible { outline: 2px solid var(--gold); outline-offset: 2px; }
button:disabled { opacity: .4; cursor: not-allowed; }

.dg-primary { background: var(--gold); color: #241a12; border-color: var(--gold); font-weight: 700; }
@media (hover: hover) { .dg-primary:hover:not(:disabled) { filter: brightness(1.08); } }

.dg-stack { display: grid; gap: .6rem; }
.dg-row { display: flex; gap: .5rem; flex-wrap: wrap; }
.dg-row3 { flex-wrap: nowrap; gap: .35rem; }
.dg-row3 > button { flex: 1 1 0; min-width: 0; white-space: nowrap; padding-left: .3rem; padding-right: .3rem; font-size: .88rem; }
/* Pushed to the right-hand end of its row. */
.dg-rightmost { margin-left: auto; }

/* The update card at the top of About. The button is the point of the
   card, so it gets the full width rather than sitting in a corner, and
   the version sits under it where you look after pressing it. */
.dg-refresh { text-align: center; }
.dg-refresh .dg-primary {
  display: inline-flex; align-items: center; justify-content: center;
  gap: .45rem; margin: .2rem 0 .5rem; padding: .55rem 1.1rem;
}
.dg-refresh p { margin: .35rem 0; }

/* The two decks at the top of the page, side by side, half the width each.
   Sized and coloured like the drill buttons under them so the group reads
   as one set of choices rather than a toolbar above a list. */
.dg-deckpair { display: grid; grid-template-columns: 1fr 1fr; gap: .4rem; margin-bottom: .4rem; }
.dg-deckpick {
  display: flex; align-items: center; justify-content: center; gap: .45rem;
  min-width: 0; padding: .7rem .5rem;
  background: transparent; border: 1px solid var(--edge); border-radius: .5rem;
  color: var(--ink); font-size: .88rem; text-align: center;
  white-space: nowrap; touch-action: manipulation;
}
/* Both labels on one line each. "Letter Flashcards" is the long one and
   wrapped at .95rem in half a 375px screen, which left the two buttons
   different heights - the one thing a pair of equals must not be. */
.dg-deckpick .dg-ico { color: var(--gold); font-size: 1rem; line-height: 1; flex: 0 0 auto; }
.dg-deckpick-label { min-width: 0; }
@media (hover: hover) { .dg-deckpick:hover { border-color: var(--gold); } }
.dg-deckpick:active { background: rgba(255,255,255,.05); }

/* How far through a set you are: four dots, then a tick. Narrow on
   purpose - it rides on a row that is already carrying a name, a count and
   sometimes a Sets control, and it is the thing you glance at rather than
   the thing you read. */
.dg-mastery {
  flex: 0 0 auto; align-self: center;
  display: flex; align-items: center; justify-content: center; gap: 2px;
  width: 1.5rem; height: 1.4rem;
}
/* Two by two rather than four across, inside a set row.
   Four in a line took 36px off a label that was already wrapping to three
   lines; stacked they take half that and read just as well, because what
   is being counted is how many are filled rather than where they sit. */
.dg-stack .dg-mastery { flex-wrap: wrap; width: 1rem; gap: 2px; }
.dg-stack .dg-mastery[data-done="1"] { width: 1.5rem; }
.dg-mastery[data-empty="1"] { visibility: hidden; }
.dg-dot {
  width: 5px; height: 5px; border-radius: 50%;
  background: var(--edge); flex: 0 0 auto;
}
.dg-mastery[data-done="1"] { gap: 0; }
.dg-mastery-tick {
  display: flex; align-items: center; justify-content: center;
  width: 1.4rem; height: 1.4rem; border-radius: 50%;
  background: #86e08f; color: #1c1530;
  font-size: .9rem; font-weight: 700; line-height: 1;
}

/* The standing of the set being practised, shown large above the menu.
   Five slots: four that fill as the set comes together and a fifth that
   turns green when every card in it is currently right. Fixed to the
   bottom so it stays put as the questions scroll under it. */
.dg-strip {
  position: fixed; left: 0; right: 0; bottom: var(--footh);
  z-index: 5; pointer-events: none;
  display: flex; align-items: center; justify-content: center; gap: .55rem;
  padding: .45rem 0 .5rem;
  background: linear-gradient(to top, var(--ground) 62%, transparent);
}
/* Empty has to read as empty at a glance and from arm's length, so the
   unfilled slot carries its own faint fill and a border light enough to
   find against the ground. An outline nobody can see is not a count. */
.dg-slot {
  width: 14px; height: 14px; border-radius: 50%;
  background: rgba(255, 241, 217, .09);
  border: 1.5px solid rgba(255, 241, 217, .4);
  flex: 0 0 auto;
}
.dg-slot[data-on="1"] { border-color: transparent; }
/* The last one is the finish, so it is bigger and carries the tick. */
.dg-slot-last {
  width: 22px; height: 22px; border-width: 2px;
  display: flex; align-items: center; justify-content: center;
  font-size: .8rem; font-weight: 700; line-height: 1; color: transparent;
}
.dg-slot-last[data-on="1"] {
  background: #86e08f; border-color: #86e08f; color: #1c1530;
}

/* Everything showing, as one bar of dots - four for every set, the same
   four the menu shows on the row. Wraps into as many lines as it needs;
   the shape of the block is itself the size of the course. */
.dg-bar {
  display: flex; flex-wrap: wrap; gap: 3px;
  margin: .2rem 0 .5rem;
}
.dg-bardot {
  width: 6px; height: 6px; border-radius: 50%;
  background: var(--edge); flex: 0 0 auto;
}
.dg-bardot[data-on="1"] { background: var(--green); }
/* Practice Mastery, in its three domains: pale in the domain's colour
   while still to do, white ringed brightly in it once done. */
.dg-bar-l { --dc: var(--dom-l); } .dg-bar-v { --dc: var(--dom-v); } .dg-bar-g { --dc: var(--dom-g); }
.dg-bar-l, .dg-bar-v, .dg-bar-g { gap: 4px; margin: 0 0 .75rem; }
.dg-bar-l .dg-bardot, .dg-bar-v .dg-bardot, .dg-bar-g .dg-bardot {
  width: 7px; height: 7px; background: var(--dc); opacity: .32;
}
.dg-bar-l .dg-bardot[data-on="1"], .dg-bar-v .dg-bardot[data-on="1"], .dg-bar-g .dg-bardot[data-on="1"] {
  background: #fff; opacity: 1; box-shadow: 0 0 0 1.5px var(--dc), 0 0 5px var(--dc);
}

/* An area, and whether it is on the menu at all. */
.dg-area {
  display: flex; align-items: center; gap: .5rem;
  margin: .9rem 0 .2rem; padding-bottom: .2rem;
  border-bottom: 1px solid var(--edge);
}
.dg-area-name {
  flex: 1 1 auto; font-size: .78rem; letter-spacing: .08em;
  text-transform: uppercase; color: var(--ink-dim);
}
.dg-area-toggle {
  flex: 0 0 auto; padding: .2rem .5rem; font-size: .75rem;
  background: transparent; border: 1px solid var(--edge); border-radius: .3rem;
  color: var(--ink-dim); touch-action: manipulation;
}
.dg-area-toggle[aria-pressed="true"] { color: var(--gold); border-color: var(--gold); }
@media (hover: hover) { .dg-area-toggle:hover { color: var(--ink); } }

/* The curriculum list on Progress: dots, name, the exact count, and the
   way to start that one again. */
.dg-curri {
  display: flex; align-items: center; gap: .5rem;
  padding: .3rem 0 .3rem .6rem;
}
.dg-curri-head { padding-left: 0; margin-top: .5rem; }
.dg-curri-head .dg-curri-name { font-weight: 700; color: var(--ink); }
.dg-curri-name {
  flex: 1 1 auto; min-width: 0; font-size: .9rem; color: var(--ink-dim);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.dg-curri-num {
  flex: 0 0 auto; font-size: .82rem; color: var(--ink-dim);
  font-variant-numeric: tabular-nums;
}
.dg-curri-reset {
  flex: 0 0 auto; padding: .2rem .45rem; font-size: .75rem;
  background: transparent; border: 1px solid var(--edge); border-radius: .3rem;
  color: var(--ink-dim); touch-action: manipulation;
}
@media (hover: hover) { .dg-curri-reset:hover { border-color: var(--gold); color: var(--ink); } }
/* Asked once, and saying so: the second press is the one that acts. */
.dg-curri-reset.dg-armed { border-color: var(--red); color: var(--red); }

/* -------------------------------------------------------- menu cards */

.dg-card {
  background: var(--raised); border: 1px solid var(--edge);
  border-radius: .6rem; padding: .9rem 1rem; margin-bottom: .75rem;
}
/*
 * The last thing in a card does not add its own margin to the card's.
 *
 * Every row inside carries a bottom margin to separate it from the next
 * row, and the last one has no next row - so it was quietly adding itself
 * to the padding underneath. A card with one row in it measured sixteen
 * pixels above and twenty-five below, which is the sort of lopsidedness
 * you feel down a page of ten of them without being able to name.
 */
.dg-card > *:last-child { margin-bottom: 0; }

/*
 * The menu cards run tighter than the reading ones.
 *
 * A card on About holds paragraphs and wants room around them; a card on
 * the menu holds one row and is a target. Ten of those down a page, each
 * with a centimetre of air it is not using, is most of a screen spent on
 * nothing - so these keep the side padding and give up the vertical.
 */
.dg-menucard { padding-top: .5rem; padding-bottom: .5rem; margin-bottom: .45rem; }
.dg-set {
  display: flex; align-items: center; justify-content: space-between;
  gap: .75rem; width: 100%; text-align: left;
}
.dg-set .dg-set-label { font-family: var(--deva); }

/* The Continue button reads as two lines: the word, then the set you are
   returning to. */
.dg-continue .dg-set-label { display: block; font-family: var(--serif); }
.dg-continue .dg-conthead {
  display: block; font-family: var(--serif);
  font-size: .82rem; letter-spacing: .02em; opacity: .75;
}
.dg-continue .dg-contset { display: block; font-family: var(--deva), var(--serif); }
.dg-set .dg-set-meta { color: var(--ink-dim); font-size: .85rem; white-space: nowrap; }

/* A category is one unrolled option plus More…, which opens the sets below
   it. The unrolled option is the whole category — what most people want most
   of the time — so the individual sets are never something to read past. */
/* Over on the right, away from the set names that run down the left edge:
   it is a control on the card rather than another thing to choose. */
.dg-more {
  display: block; margin-left: auto;
  background: transparent; border: 0;
  color: var(--ink-dim); font-size: .85rem; letter-spacing: .04em;
  padding: .45rem .1rem .1rem; text-align: right;
}
@media (hover: hover) { .dg-more:hover { color: var(--gold); } }
.dg-more[aria-expanded="true"] { color: var(--gold); }

.dg-grouphead {
  font-size: .8rem; text-transform: uppercase; letter-spacing: .1em;
  color: var(--ink-dim); font-weight: 400; margin: 1.4rem 0 .5rem;
}

.dg-all { border-color: rgba(220,193,81,.45); margin-bottom: .5rem; font-size: 1.02rem; }
.dg-all:last-child { margin-bottom: 0; }

/* Vocabulary reads green, letters read gold, so which half of the game you
   are in is obvious before you read a word of it. */
.dg-vocab { background: rgba(86,136,90,.16); border-color: rgba(86,136,90,.45); }
.dg-vocab .dg-all { border-color: rgba(127,184,132,.45); background: rgba(86,136,90,.22); }
@media (hover: hover) { .dg-vocab .dg-all:hover { border-color: var(--green); } }
.dg-vocab .dg-mode[aria-pressed="true"] { border-color: var(--green); color: var(--green); }
@media (hover: hover) { .dg-vocab .dg-more:hover, .dg-vocab .dg-more[aria-expanded="true"] { color: var(--green); } }
.dg-vocab-btn { background: rgba(86,136,90,.22); border-color: rgba(127,184,132,.5); }
@media (hover: hover) { .dg-vocab-btn:hover { border-color: var(--green); } }

/* Grammar reads gold: a third thing, neither an alphabet nor a word list. */
.dg-gram { background: rgba(220,193,81,.13); border-color: rgba(220,193,81,.42); }
.dg-gram .dg-all { border-color: rgba(220,193,81,.5); background: rgba(220,193,81,.18); }
@media (hover: hover) { .dg-gram .dg-all:hover { border-color: var(--gold); } }
.dg-gram .dg-mode[aria-pressed="true"] { border-color: var(--gold); color: var(--gold); }
@media (hover: hover) { .dg-gram .dg-more:hover, .dg-gram .dg-more[aria-expanded="true"] { color: var(--gold); } }
.dg-simple { border-color: var(--gold); }
.dg-primary-set { background: var(--gold); color: #241a12; border-color: var(--gold); }
.dg-primary-set .dg-set-meta { color: #4a3a22; }

.dg-modes { display: grid; grid-template-columns: repeat(2, 1fr); gap: .4rem; margin: .2rem 0 .5rem; }
.dg-mode { font-size: .85rem; padding: .5rem .5rem; text-align: center; }
/* Both columns, so the longest label has room to stay on one line. */
.dg-mode-wide { grid-column: 1 / -1; }
.dg-mode[aria-pressed="true"] { border-color: var(--gold); color: var(--gold); }

/* ------------------------------------------------- typed + flashcards */

.dg-typedrow { display: flex; align-items: center; gap: .6rem; margin-bottom: .7rem; }
.dg-typedrow input { margin: 0; flex: 1 1 auto; }
.dg-char-word { font-family: var(--deva); font-size: 1.7rem; min-width: 4.5rem; }
.dg-play-inline {
  position: static; width: 2.6rem; height: 2.6rem;
  align-items: center; justify-content: center; padding: .2rem;
  flex: 0 0 auto;
}

.dg-flash .dg-flashhead { display: flex; align-items: center; gap: .5rem; margin-bottom: .5rem; }
.dg-flash .dg-reveal { border-top: 1px solid var(--edge); padding-top: .6rem; margin-top: .5rem; }
.dg-flash .dg-iast { color: var(--gold); font-style: italic; margin-bottom: .3rem; }
.dg-flashbtns button[aria-pressed="true"] { border-color: var(--gold); color: var(--gold); }

.dg-hook-soft { border-left-color: var(--ink-dim); }

/* ------------------------------------------------------ stats + reset */

.dg-resetrow { align-items: center; margin-top: .8rem; }
.dg-help {
  width: 2.1rem; height: 2.1rem; padding: 0; border-radius: 50%;
  font-weight: 700; line-height: 1; flex: 0 0 auto;
}
.dg-help[aria-expanded="true"] { border-color: var(--gold); color: var(--gold); }

/* ----------------------------------------------------- saving & linking */

.dg-code {
  display: flex; align-items: baseline; gap: .75rem; flex-wrap: wrap;
  background: var(--ground); border: 1px solid var(--gold);
  border-radius: .5rem; padding: .7rem .9rem; margin: .7rem 0;
}
.dg-codeval {
  font-size: 1.9rem; font-weight: 700; letter-spacing: .28em;
  color: var(--gold); font-variant-numeric: tabular-nums;
}
/* A save the eye catches: the button itself confirms, then goes back. */
/* Give the name the slack and keep the country narrow, so a board row stays
   one line at phone width. */
.dg-table td.dg-nm { width: 46%; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.dg-table td.dg-ct { width: 22%; white-space: nowrap; color: var(--ink-dim); }
.dg-table td.dg-num, .dg-table th.dg-num { width: 16%; white-space: nowrap; }
.dg-table th, .dg-table td { padding: .4rem .35rem; }

.dg-table tr.dg-you td { color: var(--gold); font-weight: 700; }

.dg-saved {
  background: var(--green) !important;
  border-color: var(--green) !important;
  color: #10210f !important;
  opacity: 1 !important;
}

.dg-device {
  display: flex; align-items: center; gap: .6rem; flex-wrap: wrap;
  background: var(--raised); border: 1px solid var(--edge);
  border-radius: .5rem; padding: .6rem .75rem;
}
.dg-device .dg-set-label { flex: 1 1 auto; }
.dg-unlink { padding: .3rem .6rem; font-size: .82rem; flex: 0 0 auto; }
@media (hover: hover) { .dg-unlink:hover { border-color: var(--red); color: var(--red); } }

.dg-linkinput { /* the input belonging to whichever link panel is open */ }
.dg-linkjump {
  width: 100%; margin-top: .8rem; text-align: left;
  font-size: .9rem; color: var(--gold);
  background: transparent; border: 1px dashed var(--edge);
}
@media (hover: hover) { .dg-linkjump:hover { border-color: var(--gold); border-style: solid; } }

/* ------------------------------------------------------ chart overlay */

/* Sits above everything including the footer, because it is opened mid-
   question and should cover the question, not fight it for space. Tapping
   the backdrop OR the image closes it; the control bar stops propagation so
   the arrows do not dismiss on the way to the next chart. */
/* Stops short of the footer rather than covering it: the Chart button must
   stay reachable, so the same tap that opened this closes it again. */
.dg-chartwrap {
  position: fixed; left: 0; right: 0; top: 0;
  bottom: calc(var(--footh) + var(--sab));
  z-index: 60;
  background: rgba(12,9,22,.93);
  -webkit-backdrop-filter: blur(6px); backdrop-filter: blur(6px);
  display: flex; flex-direction: column; align-items: center; justify-content: flex-start;
  gap: .75rem; padding: 1rem;
  cursor: zoom-out;
}
/* The image is sized by WIDTH and the frame scrolls, rather than the image
   being shrunk to fit the frame. Fitting made the full table unreadable on a
   phone; this way it fills the width at 1x and the zoom control scales only
   the image, never the page. */
/* The frame is free to use the whole window — that is what makes a zoomed
   chart worth zooming. It shrinks to the image when the image is short, so
   the outer centring handles the vertical, and scrolls when it is not. */
.dg-chartscroll {
  flex: 1 1 auto; min-height: 0; max-height: 100%;
  width: 100%;
  overflow: auto; -webkit-overflow-scrolling: touch;
  border-radius: .5rem; border: 1px solid var(--edge);
  background: #16203a; cursor: auto;
}
/* margin auto rather than flex or grid centring: when the image is WIDER than
   the frame, auto margins resolve to zero and it simply scrolls. Centring a
   scroll container with flex or place-content clips the left edge instead. */
.dg-chartimg {
  display: block; margin: 0 auto;
  width: calc(100% * var(--chartzoom, 1));
  max-width: none !important; height: auto !important;
}
.dg-charttools {
  display: flex; align-items: center; gap: .5rem;
  width: 100%; max-width: var(--col); cursor: auto;
}
.dg-chartname { flex: 1 1 auto; color: var(--ink-dim); font-size: .85rem; }
.dg-charttool {
  padding: .35rem .6rem; font-size: .85rem; background: var(--raised);
}
.dg-zoomval {
  font-size: .78rem; color: var(--ink-dim); font-variant-numeric: tabular-nums;
  min-width: 2.6rem; text-align: center; flex: 0 0 auto;
}
.dg-charttools .dg-zoomval { font-size: .85rem; }

/* Pinned to the floor of the overlay rather than floating under whatever
   height the image happened to be, so the two buttons are in the same place
   on every chart. */
.dg-chartbar {
  display: flex; gap: .5rem; width: 100%; max-width: var(--col); cursor: auto;
  margin-top: auto; flex: 0 0 auto;
}
.dg-chartnav {
  flex: 1 1 0; min-width: 0; height: 3rem;
  display: flex; align-items: center; justify-content: center;
  gap: .4rem; font-size: .85rem; padding: 0 .5rem; line-height: 1.25;
  text-align: center;
}
/* One line, cut short if the chart's name is long: a label that wraps makes
   the button taller than the one beside it. */
.dg-navtext {
  min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.dg-chartnav .dg-arrow { color: var(--gold); font-size: 1.1rem; line-height: 1; }

@media (min-width: 40rem) {
  .dg-chartimg { max-height: 74vh; }
  .dg-chartnav { font-size: .9rem; }
}

/* ------------------------------------------------------- docked chart */

/*
 * The in-page answer to "keep the chart up while I answer". A web page cannot
 * ask the OS for split screen — Android users can split two browser windows
 * themselves, iOS has no equivalent — so the split happens inside the page:
 * the chart pins to the top and the game scrolls beneath it.
 */
.dg-dock {
  position: fixed; top: 0; left: 0; right: 0; z-index: 65;
  height: var(--dockh);
  background: #16203a;
  border-bottom: 1px solid var(--edge);
  display: flex; flex-direction: column;
  padding-top: var(--sat);
}
.dg-dockscroll {
  flex: 1 1 auto; min-height: 0; overflow: auto;
  -webkit-overflow-scrolling: touch;
}
.dg-dockimg {
  display: block; margin: 0 auto;
  width: calc(100% * var(--chartzoom, 1));
  max-width: none !important; height: auto !important;
}
/* The controls keep the game's own column even though the chart beside them
   may span the window, so the eye is not asked to travel further for the
   buttons than for anything else on the page. */
.dg-dockbar {
  display: flex; align-items: center; gap: .3rem;
  padding: .25rem .4rem; border-top: 1px solid rgba(67,53,107,.6);
  background: rgba(28,21,48,.6);
}
.dg-dockbar-inner {
  display: flex; align-items: center; gap: .3rem;
  width: 100%; max-width: var(--col); margin: 0 auto;
}
.dg-dockbar .dg-dockname {
  flex: 1 1 auto; font-size: .72rem; color: var(--ink-dim);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.dg-dockbtn {
  padding: .2rem .45rem; font-size: .8rem; line-height: 1.2;
  background: var(--raised); border-radius: .35rem;
}
/* The flip button changes from an icon to a word, so it is given the width
   of the word: otherwise the whole bar shuffles sideways on every flip. */
.dg-dockflip { min-width: 3.4rem; text-align: center; }

/* In a game the page is exactly the screen: the room kept below is just
   the menu's own height, so nothing scrolls by a strip of empty space. */
body.dg-playing #dg-app { padding-bottom: calc(4.2rem + var(--sab)); }
body.dg-docked #dg-app { padding-top: calc(var(--dockh) + var(--sat) + .75rem); }

/* ------------------------------------------------- Devanagari keyboard */

/* Fills the panel the chart would fill. The rows scroll; the action row
   does not, because backspace should never need hunting for. */
.dg-kb { flex: 1 1 auto; min-height: 0; display: flex; flex-direction: column; }
.dg-kbscroll {
  flex: 1 1 auto; min-height: 0; overflow: auto;
  -webkit-overflow-scrolling: touch;
  width: 100%; max-width: var(--col); margin: 0 auto; padding: 0 .4rem .3rem;
}
.dg-kblabel {
  font-size: .6rem; text-transform: uppercase; letter-spacing: .09em;
  color: var(--ink-dim); margin: .35rem 0 .15rem;
}
/* Each row is its own flex line rather than one wrapping grid, so the five
   vargas stay five to a line the way the chart prints them. */
.dg-kbrow { display: flex; gap: .25rem; margin-bottom: .25rem; }
.dg-key {
  flex: 1 1 0; min-width: 0;
  padding: .3rem .1rem; border-radius: .35rem;
  background: var(--raised); border: 1px solid var(--edge); color: var(--ink);
  font-family: var(--deva), var(--serif); font-size: 1.15rem; line-height: 1.25;
  text-align: center;
}
@media (hover: hover) { .dg-key:hover { border-color: var(--gold); } }
.dg-key:active { background: var(--gold); color: #1c1530; }
.dg-kbactions {
  display: flex; gap: .25rem;
  width: 100%; max-width: var(--col); margin: 0 auto; padding: .25rem .4rem;
  border-top: 1px solid rgba(67,53,107,.6);
}
.dg-key-wide { font-family: var(--serif); font-size: .85rem; }

/* The answer box for a Devanagari round, and the transliteration cue beside
   it: the cue is what you read, so it gets the gold the prompt side uses
   elsewhere. */
.dg-devainput { font-family: var(--deva), var(--serif); font-size: 1.15rem; }
.dg-cue { font-style: italic; color: var(--gold); font-size: 1.05rem; }
.dg-typedrow .dg-cue { min-width: 4.5rem; }

/* ---------------------------------------------------------- more menu */

/* Narrow boxes stacked against the right-hand edge, under the More button
   they belong to, so the sheet reads as that button opening upward rather
   than as a bar that happens to appear. */
.dg-sheet {
  max-width: var(--col); margin: 0 auto; padding: .4rem .5rem .1rem;
  border-bottom: 1px solid var(--edge);
  display: flex; flex-direction: column; align-items: flex-end; gap: .3rem;
}
.dg-sheetitem {
  display: flex; align-items: center; gap: .6rem;
  padding: .6rem .7rem; border-radius: .45rem;
  background: var(--raised); border: 1px solid var(--edge);
  color: var(--ink); text-decoration: none; font-size: .95rem;
  width: auto; min-width: 10.5rem; max-width: 100%;
  text-align: left; font-family: inherit;
}
@media (hover: hover) { .dg-sheetitem:hover { border-color: var(--gold); } }
.dg-sheetitem .dg-ico { color: var(--gold); font-size: 1.05rem; }

/* The sheet lives inside the footer nav, so `.dg-foot button` — which
   stacks an icon over a tiny centred caption — was winning over
   `.dg-sheetitem` for the rows that happen to be buttons. Every row in the
   sheet is a row, whatever element it is made of. */
.dg-foot .dg-sheetitem {
  flex: 0 0 auto;
  flex-direction: row; justify-content: flex-start; gap: .6rem;
  padding: .6rem .7rem; font-size: .95rem; color: var(--ink);
  background: var(--raised); border: 1px solid var(--edge);
}
.dg-foot .dg-sheetitem .dg-ico { font-size: 1.05rem; color: var(--gold); }
.dg-foot .dg-sheetitem:disabled { opacity: .45; }
.dg-foot .dg-sheetitem:disabled .dg-ico { color: var(--ink-dim); }

/* ------------------------------------------------------------ questions */

.dg-prompt { color: var(--ink-dim); margin-bottom: 1rem; }

.dg-qrow { display: flex; gap: .5rem; justify-content: center; margin: 0 0 1.25rem; flex-wrap: wrap; }

.dg-q {
  position: relative;
  flex: 1 1 0; min-width: 3.75rem; max-width: 6rem;
  background: var(--raised); border: 2px solid var(--edge);
  border-radius: .6rem; padding: .6rem .25rem .45rem; text-align: center;
}
.dg-q[data-active="1"] { border-color: var(--gold); }
.dg-q .dg-char {
  font-family: var(--deva); font-size: 2.6rem; line-height: 1.15;
  display: block; margin-bottom: .1rem;
}
.dg-q .dg-slot {
  font-variant-numeric: tabular-nums; font-size: 1rem; color: var(--gold);
  min-height: 1.4em; display: block;
}
.dg-q .dg-slot:empty::before { content: "·"; color: var(--edge); }

/*
 * The hit area is 44px, the glyph stays small.
 *
 * It was 22x17 in the corner of the tile, which on a phone is a miss more
 * often than a hit - and a miss landed on the tile behind it, whose job is
 * to CLEAR your answer. So it read as "the play button does nothing" while
 * quietly undoing the thing you had just tapped. The mark is still a small
 * triangle in the corner; what grew is the part your thumb has to find.
 */
.dg-play {
  position: absolute; top: 0; right: 0;
  width: 2.6rem; height: 2.6rem;
  display: flex; align-items: flex-start; justify-content: flex-end;
  padding: .3rem .4rem; font-size: .8rem; line-height: 1;
  background: transparent; border: 0; color: var(--ink-dim);
  touch-action: manipulation;
}
@media (hover: hover) { .dg-play:hover { color: var(--gold); } }
.dg-play:active { color: var(--gold); }
.dg-play[hidden] { display: none; }

/* Options as one continuous text block, two to a visual line on a narrow
   screen — the spec's layout, done with a grid so it stays honest at any
   width instead of depending on a 35-character guess. */
.dg-options { display: grid; grid-template-columns: repeat(2, 1fr); gap: .5rem; margin-bottom: 1rem; }
@media (min-width: 34rem) { .dg-options { grid-template-columns: repeat(3, 1fr); } }

.dg-opt { display: flex; gap: .45rem; align-items: baseline; text-align: left; line-height: 1.3; }
.dg-opt .dg-n { font-family: var(--deva); color: var(--gold); font-weight: 600; flex: 0 0 auto; }
.dg-opt .dg-label { font-size: .95rem; }
.dg-opt[data-used="1"] { opacity: .45; }

.dg-typed {
  display: flex; gap: .5rem; align-items: center; flex-wrap: wrap;
  margin-bottom: 1rem;
}
/* The field takes whatever the return key leaves, so it is ready for the
   longer answers vocabulary and grammar will want. `width: auto` is load
   bearing: the generic input rule sets 100%, which would push the key onto
   a line of its own. */
.dg-typed input[type="text"] {
  flex: 1 1 auto; width: auto; min-width: 0; margin: 0;
  font-family: var(--deva), var(--serif); font-size: 1.1rem;
  letter-spacing: .25em; padding: .6rem .7rem; color: var(--ink);
  background: var(--ground); border: 1px solid var(--edge); border-radius: .5rem;
}
.dg-typed input:focus { outline: none; border-color: var(--gold); }
.dg-typed .dg-err { flex: 1 1 100%; }

/* The return key: square, so it reads as a key rather than a word, and a
   fixed size so the field beside it never shifts. */
.dg-enter {
  flex: 0 0 auto; min-width: 3rem; padding: .55rem .8rem;
  font-size: 1.25rem; line-height: 1.1;
}

/* -------------------------------------------------------------- results */

.dg-results { margin: 0 0 1rem; padding: 0; list-style: none; }
.dg-result {
  display: flex; gap: .5rem; align-items: baseline; flex-wrap: wrap;
  padding: .35rem 0; border-bottom: 1px solid rgba(67,53,107,.5);
}
/*
 * Zero basis, free to grow. A flex line that is allowed to WRAP moves a
 * too-wide item to the next line rather than shrinking it, so an answer
 * sized by its text would jump a line the moment anything beside it grew -
 * which is exactly what happened when the play button reached 44px. With no
 * basis it can never be too wide: it takes what is left and wraps its own
 * text, and the tick keeps its place at the end.
 */
.dg-result .dg-answer { flex: 1 1 0; min-width: 0; }
.dg-result .dg-char { font-family: var(--deva); font-size: 1.5rem; }
/* The play button is absolutely positioned inside a question tile, but in a
   result row it is just an inline control. Without this it escapes its li —
   whose position is static — and lands in the top corner of the page. */
.dg-result .dg-play {
  position: static; align-self: center; flex: 0 0 auto;
  width: 2.4rem; height: 2.4rem; padding: 0;
  align-items: center; justify-content: center;
}
.dg-result .dg-dash { color: var(--ink-dim); }
/* The answer is the line you are actually reading on this screen, so it is
   set two points above everything around it. */
.dg-result .dg-answer { font-size: calc(1rem + 2px); }
.dg-result .dg-n { font-family: var(--deva); color: var(--gold); }

/* Debug log: a monospaced dump that keeps its own line breaks, and a
   textarea for browsers that will not hand us the clipboard. */
.dg-pre { white-space: pre-wrap; font-family: ui-monospace, Menlo, monospace; font-size: .68rem; }
.dg-dump {
  width: 100%; height: 9rem; margin-top: .5rem;
  font-family: ui-monospace, Menlo, monospace; font-size: .68rem;
  color: var(--ink); background: var(--ground);
  border: 1px solid var(--edge); border-radius: .4rem; padding: .4rem;
}
.dg-result .dg-mark { flex: 0 0 auto; margin-left: .35rem; font-size: 1.1rem; }
/* Your own answer, on its own line under the right one. Quiet, because it
   is there to be checked against, not to be read first. */
.dg-result .dg-yours {
  flex: 1 1 100%; font-size: .82rem; color: var(--ink-dim);
  padding-left: 1.6rem;
}
.dg-result[data-ok="1"] .dg-mark { color: var(--green); }
.dg-result[data-ok="0"] .dg-mark { color: var(--red); }

.dg-hook {
  background: var(--raised); border-left: 3px solid var(--gold);
  border-radius: 0 .4rem .4rem 0; padding: .65rem .8rem; margin: .5rem 0 .9rem;
  font-size: .95rem; color: var(--ink-dim);
}
.dg-hook .dg-hook-char { font-family: var(--deva); color: var(--ink); font-size: 1.15rem; margin-right: .35rem; }

/* ---------------------------------------------------------- leaderboard */

.dg-table { width: 100%; border-collapse: collapse; font-size: .95rem; }
.dg-table th, .dg-table td { text-align: left; padding: .4rem .5rem; border-bottom: 1px solid rgba(67,53,107,.5); }
.dg-table th { color: var(--ink-dim); font-weight: 400; font-size: .85rem; }
.dg-table td.dg-num { text-align: right; font-variant-numeric: tabular-nums; }

/* --------------------------------------------------------------- forms */

label { display: block; font-size: .9rem; color: var(--ink-dim); margin-bottom: .25rem; }
input[type="text"], input[type="email"], textarea, select {
  width: 100%; font-family: inherit; font-size: 1rem; color: var(--ink);
  background: var(--ground); border: 1px solid var(--edge);
  border-radius: .5rem; padding: .6rem .7rem; margin-bottom: .8rem;
}
textarea { min-height: 7rem; resize: vertical; }
input:focus, textarea:focus, select:focus { outline: none; border-color: var(--gold); }

.dg-check { display: flex; gap: .5rem; align-items: flex-start; margin-bottom: .8rem; }
.dg-check input { width: auto; margin: .2rem 0 0; }
.dg-check label { margin: 0; color: var(--ink); font-size: .95rem; }

/* The honeypot. Off-screen rather than display:none — some bots skip
   hidden fields but happily fill positioned ones. */
.dg-hp { position: absolute; left: -9999px; width: 1px; height: 1px; overflow: hidden; }

.dg-note { font-size: .88rem; color: var(--ink-dim); }
.dg-ok  { color: var(--green); }
.dg-err { color: var(--red); }

/* --------------------------------------------------------- footer menu */

.dg-foot {
  position: fixed; left: 0; right: 0; bottom: 0; z-index: 70;
  background: rgba(28,21,48,.94);
  -webkit-backdrop-filter: blur(8px); backdrop-filter: blur(8px);
  border-top: 1px solid var(--edge);
  padding-bottom: var(--sab);
}
.dg-foot-inner {
  max-width: var(--col); margin: 0 auto;
  display: flex; justify-content: space-around; gap: .25rem; padding: .3rem .5rem;
}
.dg-foot button {
  background: transparent; border: 0; border-radius: .4rem;
  padding: .45rem .3rem; flex: 1 1 0;
  display: flex; flex-direction: column; align-items: center; gap: .1rem;
  font-size: .68rem; color: var(--ink-dim); letter-spacing: .02em;
}
/* Every icon on the bar sits in the same box - a glyph, the house drawn
   in SVG, the mark as an image - so the icons are one height and the
   words under them line up. */
.dg-foot button .dg-ico,
.dg-foot button .dg-foot-markimg {
  height: 1.45rem; font-size: 1.1rem; line-height: 1.45rem;
  display: flex; align-items: center; justify-content: center;
}
.dg-foot button .dg-homeico { width: auto; }
.dg-foot button .dg-homeico svg { height: 1.2rem; width: auto; }

/* Home (or Back) is one of the named buttons like the rest: the same
   width, its word under its icon. */


/* An edge slot with nothing in it. The back arrow and the mark each appear
   on some screens and not others; holding their space open on the rest is
   what keeps Practice, Progress and Chart from sliding sideways as you move
   between screens. */
.dg-slot-empty { visibility: hidden; pointer-events: none; }

/* The mark, bottom right: About. */
.dg-foot .dg-aboutbtn .dg-foot-markimg { width: 1.45rem; padding: .14rem; box-sizing: border-box; border-radius: 50%; object-fit: contain; }

/* With the masthead gone from a round, the mark holds the brand down here.
   It is decoration, not a button: no flex growth, no pointer. */
.dg-foot-mark {
  flex: 0 0 auto; width: 1.9rem; height: 1.9rem;
  align-self: center; margin-left: .2rem; opacity: .9;
  pointer-events: none;
}
.dg-foot button[aria-current="page"] { color: var(--gold); }
@media (hover: hover) { .dg-foot button:hover:not(:disabled) { color: var(--ink); } }
.dg-foot button:disabled { opacity: .35; }
.dg-foot button:disabled[aria-current="page"] { opacity: 1; cursor: default; }
.dg-foot .dg-pausefoot { color: var(--gold); }

.dg-soon {
  display: inline-block; font-size: .6rem; text-transform: uppercase;
  letter-spacing: .08em; color: var(--ink-dim); border: 1px solid var(--edge);
  border-radius: 1rem; padding: 0 .35rem; margin-left: .35rem; vertical-align: .1em;
}

@media (prefers-reduced-motion: reduce) { * { transition: none !important; } }

/* --------------------------------------------------------- flashcards */

/* The switches above a card. Quieter than the card itself. */
.dg-deckrow { display: flex; gap: .4rem; margin: .25rem 0 .6rem; }
.dg-deckbtn {
  flex: 1 1 0; display: flex; align-items: center; justify-content: center;
  gap: .35rem; padding: .35rem .3rem; font-size: .78rem;
  color: var(--ink-dim); background: transparent; border: 1px solid var(--edge);
}
@media (hover: hover) { .dg-deckbtn:hover { color: var(--ink); border-color: var(--gold); } }
.dg-deckbtn .dg-ico { font-size: .9rem; line-height: 1; color: var(--gold); }

/*
 * The card sits in the bottom half of the screen, because that is where a
 * thumb is. The wrap takes the whole height and pushes it down; the card
 * itself is a box with an arrow column down each side, each the full height
 * of the card, so the target is the whole edge rather than a button to aim
 * at.
 */
.dg-cardwrap {
  display: flex; flex-direction: column; justify-content: flex-end;
  /*
   * A floor, not the layout. The real sizing is done by the flex rule
   * further down, which lets the browser work out what is left instead of
   * subtracting a list of constants - a list that was wrong the moment the
   * docked chart took a third of the screen, and would have gone wrong
   * again every time anything was added above the card.
   */
  min-height: 9rem;
  gap: .5rem;
}
.dg-card-flash {
  display: flex; align-items: stretch;
  min-height: 17rem;
  background: var(--raised); border: 1px solid var(--edge); border-radius: .9rem;
  overflow: hidden;
}
.dg-cardarrow {
  flex: 0 0 3.25rem; display: flex; align-items: center; justify-content: center;
  background: transparent; border: 0; border-radius: 0;
  color: var(--ink-dim); font-size: 1.6rem; line-height: 1;
  touch-action: manipulation;
}
.dg-cardarrow-l { border-right: 1px solid var(--edge); }
/* The forward edge is a column now: the way back to the first card at the
   top of it, the arrow onward filling the rest. Both are ways through the
   deck, which is what this edge of the card is for. */
.dg-cardnext {
  flex: 0 0 3.25rem; min-width: 0;
  display: flex; flex-direction: column;
  border-left: 1px solid var(--edge);
}
.dg-cardnext .dg-cardarrow-r { flex: 1 1 auto; border-left: 0; }
@media (hover: hover) { .dg-cardarrow:hover:not(:disabled) { background: rgba(255,255,255,.04); color: var(--ink); } }
.dg-cardarrow:active:not(:disabled) { background: rgba(255,255,255,.07); }
.dg-cardarrow:disabled { opacity: .2; }

/*
 * Three rows of fixed height, so the letter does not move.
 *
 * The example word appears above it and the description below, and either
 * can be absent - on a face with no word, on a letter with no example at
 * all, or simply because the switch is off. Laid out as a centred column
 * they would each shove the letter as they came and went, which is the one
 * thing a flashcard must not do: your eye should be able to rest on the
 * spot and have the next letter arrive there. So both rows are always
 * present, empty when there is nothing to put in them, and the letter's
 * own row is fixed too - Devanagari and the transliteration are set at
 * different sizes and would otherwise shift it between the two faces.
 */
.dg-cardmid {
  position: relative; flex: 1 1 auto; min-width: 0;
  display: grid; grid-template-rows: 2.3rem 6.4rem 2.8rem; align-content: center;
  justify-items: center; padding: 1rem .5rem; text-align: center;
  cursor: pointer; touch-action: manipulation;
}
.dg-cardplay { position: absolute; top: .25rem; right: .25rem; }

/* The two faces are set at the same optical weight, so turning the card
   does not feel like changing subject. Devanagari carries more ink at a
   given size, so the transliteration is set larger to match it. */
/* Sitting low in its row rather than centred in it: the letter reads
   better with the example word clear above it and air at the top of the
   card. A transform, not a margin, so only the glyph moves - the word's
   row and the description's row keep exactly the places they had. */
.dg-cardface {
  line-height: 1.1; word-break: break-word;
  display: flex; align-items: center; justify-content: center;
  width: 100%; height: 100%;
  transform: translateY(20%);
}
.dg-cardface-deva { font-family: var(--deva); font-size: 5.5rem; color: var(--ink); }
.dg-cardface-iast { font-family: var(--serif); font-size: 4rem; font-style: italic; color: var(--gold); }
.dg-cardnote {
  color: var(--ink-dim); font-size: .85rem; margin: 0;
  display: flex; align-items: flex-start; justify-content: center;
  width: 100%; overflow: hidden;
}
.dg-cardcount { text-align: center; color: var(--ink-dim); font-size: .78rem; margin: 0; }

@media (max-width: 22rem) {
  .dg-cardmid { grid-template-rows: 2.1rem 5.4rem 2.8rem; }
  .dg-cardface-deva { font-size: 4.5rem; }
  .dg-cardface-iast { font-size: 3.2rem; }
}

/* ----------------------------------------------------- choose items */

.dg-preflist { display: flex; flex-direction: column; }
.dg-prefrow {
  display: flex; align-items: center; gap: .4rem;
  padding: .3rem 0; border-bottom: 1px solid rgba(67,53,107,.5);
}
.dg-prefhead {
  border-bottom: 1px solid var(--edge);
  font-size: .62rem; text-transform: uppercase; letter-spacing: .07em;
  color: var(--ink-dim);
}
.dg-prefitem { flex: 1 1 auto; min-width: 0; display: flex; align-items: baseline; gap: .5rem; }
.dg-prefdeva { font-family: var(--deva); font-size: 1.45rem; }
.dg-prefiast { color: var(--ink-dim); font-size: .9rem; }
.dg-prefcol { flex: 0 0 2.9rem; display: flex; justify-content: center; }
/* A 44px target around a small box, same reasoning as the play buttons. */
.dg-prefbox {
  width: 2.6rem; height: 2.6rem; padding: 0;
  display: flex; align-items: center; justify-content: center;
  background: transparent; border: 0; color: var(--gold); font-size: 1rem;
  touch-action: manipulation;
}
.dg-prefbox::before {
  content: ""; position: absolute;
  width: 1.15rem; height: 1.15rem; border-radius: .25rem;
  border: 1px solid var(--edge);
}
.dg-prefbox[aria-checked="true"]::before { border-color: var(--gold); }
.dg-prefbox { position: relative; }
.dg-prefbox > * { position: relative; }
.dg-prefrow[data-hide="both"] .dg-prefitem { opacity: .45; text-decoration: line-through; }
.dg-prefrow[data-hide="deva"] .dg-prefdeva,
.dg-prefrow[data-hide="iast"] .dg-prefiast { opacity: .35; text-decoration: line-through; }

/* ------------------------------------- flashcard controls and examples */

/* The card's own choices, centred above it: the same four the list offers,
   applied to whatever is on screen. */
/*
 * Six switches, and on a 375px phone they fit on one line with room to
 * spare. On a 320px one they do not, and the question is how they fail.
 *
 * Three ways were tried. Left alone the row ran off both edges, centred,
 * losing a switch at each end with nothing to show it had. Allowed to
 * shrink, every word collapsed into an ellipsis at once - "Exa... De...
 * C..." - which is three labels made useless to save one line. Allowed to
 * wrap, the words stay whole and the row becomes two tidy lines on the
 * narrow phone and stays one on every other. That is the one worth having:
 * a label you can read on two lines beats three you cannot on one.
 */
.dg-deckrow-top {
  justify-content: center; margin-bottom: .35rem;
  gap: .25rem; flex-wrap: wrap;
}
.dg-deckrow-top .dg-vocabtoggle, .dg-deckrow-top .dg-glosstoggle { padding: .35rem .45rem; }
.dg-deckrow-top .dg-iconbtn { padding: .35rem .34rem; }

/*
 * Below 375px the words themselves shorten, and the row stays on one line
 * after all. "Example" becomes "e.g." and "Define" becomes "Def." - short
 * enough to fit, still readable as what they are, and far better than the
 * ellipsis or the second line that were the alternatives.
 *
 * 375px because that is where it stops fitting, measured rather than
 * guessed: at 375 the full words sit on one line with a little to spare,
 * and at 360 they do not.
 */
.dg-narrow { display: none; }
@media (max-width: 374px) {
  .dg-deckrow-top .dg-wide { display: none; }
  .dg-deckrow-top .dg-narrow { display: inline; }
}
.dg-vocabtoggle, .dg-glosstoggle { flex: 0 1 auto; padding: .35rem .6rem; }
/* The two panel switches carry a picture of what they turn on and no
   word, which is what lets them share the first row with the rest. */
.dg-iconbtn { flex: 0 0 auto; padding: .35rem .42rem; gap: 0; }
/* The order switch keeps its word but gives up the padding around it, which
   is what makes room for the sound switch at the end of the row. */
/* flex: 0 1 auto, like the two beside it. On the base .dg-deckbtn the basis
   is 0, which means this button asks for no width and takes only what is
   left over - and on a narrow phone what is left over is nothing, so its
   word vanished into the ellipsis while 22px sat unused at the end of the
   row. It sizes to its content now and shrinks only if it must. */
.dg-tightbtn { flex: 0 1 auto; padding: .35rem .42rem; font-size: .8rem; }
.dg-tightbtn .dg-ico { font-size: .8rem; }

/* The speaker. Line art, to sit in a row of line drawings: the body always
   drawn, and either two waves or a cross through them. */
.dg-spkico { display: inline-flex; width: 1.05rem; flex: 0 0 auto; }
.dg-spkico svg { width: 100%; height: auto; display: block; }
.dg-sp-body { fill: currentColor; }
.dg-sp-wave { fill: none; stroke: var(--gold); stroke-width: 1.1; stroke-linecap: round; }
.dg-sp-cut  { fill: none; stroke: currentColor; stroke-width: 1.1; stroke-linecap: round; }
/* Off is the state worth seeing at a glance, so it is the one that is
   marked: gold when the sound is on, plain and struck through when it is
   not. */
.dg-soundtoggle[aria-pressed="false"] { border-color: transparent; color: var(--ink-dim); }
.dg-soundtoggle[aria-pressed="true"] { color: var(--gold); border-color: var(--gold); }

/*
 * Two kinds of switch in this row, and the border says which is which.
 *
 * Example words and Definition are on-or-off, so off means off: no border
 * either, and the state reads from across the room rather than asking you
 * to compare two shades of edge. The order switch is never off - it is
 * always in one position or the other - so it keeps its border in both,
 * because a missing border there would read as "no order", which is not a
 * thing it can be.
 */
.dg-vocabtoggle[aria-pressed="false"],
.dg-glosstoggle[aria-pressed="false"] { border-color: transparent; }
.dg-vocabtoggle[aria-pressed="true"],
.dg-glosstoggle[aria-pressed="true"] { color: var(--ink); border-color: var(--gold); }

/* Four marks and Edit deck, sharing the row end to end. */
.dg-markrow { display: flex; gap: .35rem; margin-bottom: .5rem; }
.dg-markbtn {
  flex: 1 1 0; min-width: 0;
  padding: .3rem .35rem; font-size: .74rem; line-height: 1.2; text-align: center;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
  color: var(--ink-dim); background: transparent; border: 1px solid var(--edge);
  border-radius: .35rem; touch-action: manipulation;
}
.dg-markbtn[data-on="1"] { color: #1c1530; background: var(--gold); border-color: var(--gold); }

/* The example word, in its own colour so it never reads as part of the
   letter it illustrates. It is a button because tapping it asks for the
   meaning. */
/* Always in the layout, empty when there is nothing to show, so the row
   above the letter never collapses. */
.dg-cardword {
  background: transparent; border: 0; padding: 0 .3rem;
  color: var(--brand-green); line-height: 1.2; cursor: pointer;
  display: flex; align-items: center; justify-content: center;
  width: 100%; height: 100%; overflow: hidden;
}
.dg-cardword-deva { font-family: var(--deva); font-size: 1.5rem; }
.dg-cardword-iast { font-family: var(--serif); font-size: 1.3rem; font-style: italic; }
@media (hover: hover) { .dg-cardword:hover { color: var(--ink); } }

/*
 * The meaning sits above the card, in a box that is always there.
 *
 * Reserved at five lines and empty until you ask for one, because a
 * definition appearing out of nothing would shove the card down the screen
 * - and the whole point of the rows inside the card is that the letter
 * stays put. A long gloss scrolls inside the box rather than growing it,
 * so nothing below it can move either.
 */
.dg-cardgloss {
  /* Never the thing that gives. The page is a flex column and every child
     of it can be squeezed; without this the box quietly lost two of its
     five lines as soon as a panel came up, which is the shrinking this box
     exists to prevent. The card gives instead. */
  flex: 0 0 auto;
  margin: 0 0 .4rem; text-align: center; color: var(--ink-dim);
  font-size: .85rem; line-height: 1.35;
  /* Five lines, or a seventh of the screen on a short one - a fixed box
     that is most of a small phone is worse than a shorter box that
     scrolls. The same five everywhere: docked, with the mouth up, with the
     grid up. Nothing switched on elsewhere changes this box. */
  height: min(calc(.85rem * 1.35 * 5), 15vh);
  overflow-y: auto; -webkit-overflow-scrolling: touch;
}

/* A word taken apart, inside the box the definition uses. Laid out as a
   list because that is what it is - one piece a line, the piece and then
   what it means - and scrolls inside the fixed box like a long definition
   does, so nothing below it moves. */
.dg-parts { text-align: left; padding: 0 .2rem; }
.dg-part { display: flex; gap: .4rem; align-items: baseline; line-height: 1.35; }
.dg-part-bit {
  flex: 0 0 auto; font-family: var(--deva); color: var(--gold);
  min-width: 3.2rem;
}
/* The transliteration is set in the serif and italic, as it is everywhere
   else in the game, so the two faces do not read as two different apps. */
.dg-part-iast { font-family: var(--serif); font-style: italic; }
.dg-part-gloss { min-width: 0; color: var(--ink-dim); }
/* An ending is a quieter thing than a root: it is how the word is being
   used, not what it is about. */
.dg-part-end .dg-part-bit { color: var(--ink-dim); }
/* Remarks about the whole word, indented past the column the parts sit in
   so they cannot be mistaken for another part. */
.dg-part-note {
  margin-top: .25rem; padding-left: 3.6rem;
  color: var(--ink-dim); font-size: .8rem; line-height: 1.35;
}

/* The letter being taught, picked out inside a word that does not open with
   it - a different colour from both the word and the letter below, so it
   reads as "this one, here" rather than as a third thing. */
.dg-wordmark { color: var(--gold); }
.dg-ordertoggle { border-color: var(--edge); }
.dg-ordertoggle[aria-pressed="true"] { color: var(--ink); border-color: var(--gold); }

/* The line the game is given under, at the top of About. */
.dg-dedication { color: var(--gold); font-style: italic; margin-bottom: .8rem; }

/* And the closing, at the foot of it. Set apart from the cards above
   rather than inside one: it is not information, it is how the page ends. */
.dg-colophon { text-align: center; margin: 1.6rem 0 .5rem; }
.dg-colophon-deva {
  font-family: var(--deva); font-size: 1.9rem; color: var(--ink);
  margin: 0 0 .15rem; letter-spacing: .04em;
}
.dg-colophon-iast {
  font-family: var(--serif); font-style: italic; font-size: 1rem;
  color: var(--ink-dim); margin: 0;
}

/* ------------------------------------------- the card button on the menu */

/* A start button with its deck beside it. The card button is the same
   height as whatever it sits next to, so the pair reads as one row. */
.dg-withcards { display: flex; align-items: stretch; gap: .5rem; margin-bottom: .5rem; }
/* Sets on the row rather than under it. It takes only what it needs and
   never shrinks, so the width it costs is fixed and predictable - the
   category name is what gives, which is why several of those names got
   shorter when this moved. */
.dg-setsbtn {
  flex: 0 0 auto; align-self: center; margin: 0;
  padding: .35rem .15rem; white-space: nowrap;
}
/* A category row is tighter than a plain one. Six pixels were all that
   stood between "Common Sandhi" and a second line, and they were cheaper
   to find in the gaps than in the name. */
.dg-card > .dg-withcards { gap: .35rem; }
.dg-withcards > .dg-set,
.dg-withcards > .dg-card-start { flex: 1 1 auto; min-width: 0; margin-bottom: 0; }

.dg-cardsbtn {
  flex: 0 0 auto; width: 2.9rem;
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: .1rem; padding: .3rem .2rem;
  color: var(--ink-dim); background: transparent; border: 1px solid var(--edge);
  border-radius: .5rem; touch-action: manipulation;
}
@media (hover: hover) { .dg-cardsbtn:hover { color: var(--ink); border-color: var(--gold); } }
.dg-cardsbtn .dg-ico { font-size: 1.15rem; line-height: 1; color: var(--gold); }
/* The two broad decks carry their own label; the sets below do not, because
   the set's name is already beside it. */
.dg-cardsbtn-big { width: 3.6rem; }
.dg-cardsbtn-label { font-size: .6rem; letter-spacing: .03em; }

/* Edit deck is the odd one in the marks row - not a checkbox, so it never
   fills in, and it needs the room its two words take. */
.dg-editdeck { flex: 0 0 auto; padding: .3rem .6rem; color: var(--gold); }
@media (hover: hover) { .dg-editdeck:hover { border-color: var(--gold); } }


/* ------------------------------------------------ the deck view's height */

/*
 * The deck fills the screen and the card takes whatever is left.
 *
 * Its height used to be the viewport less a list of constants, which meant
 * every addition above the card had to be remembered in a second place -
 * and it took no account of the docked chart, which claims a third of the
 * screen through padding on #dg-app. With the chart docked the sums were
 * 230px out and the page scrolled. This asks the browser instead: the page
 * is a column the height of the viewport, and the card is the part that
 * gives.
 */
body.dg-deck-view #dg-app {
  display: flex; flex-direction: column;
  min-height: 100vh; min-height: 100dvh;
}
body.dg-deck-view .dg-cardwrap { flex: 1 1 auto; }
body.dg-deck-view .dg-card-flash { flex: 0 1 auto; }

/*
 * With the chart docked, the card gives.
 *
 * A third of the screen is already spoken for, and something has to yield:
 * either the card overflows and the page scrolls - which defeats docking,
 * whose whole point is seeing the chart and the card together - or the card
 * is smaller while the chart is up. It is smaller. The rows keep their
 * fixed heights, so the letter still does not move as you turn cards; they
 * are simply shorter heights while there is a chart above them.
 */
body.dg-docked.dg-deck-view .dg-card-flash { min-height: 0; }
body.dg-docked.dg-deck-view .dg-cardmid { grid-template-rows: 1.75rem 3.9rem 2.2rem; }
body.dg-docked.dg-deck-view .dg-cardface-deva { font-size: 3.8rem; }
body.dg-docked.dg-deck-view .dg-cardface-iast { font-size: 2.8rem; }
body.dg-docked.dg-deck-view .dg-cardword-deva { font-size: 1.25rem; }
body.dg-docked.dg-deck-view .dg-cardword-iast { font-size: 1.1rem; }

/* ----------------------------------------------- above the card: the mouth */

/* Two halves. The diagram takes the left; the right is deliberately empty,
   waiting for whatever belongs beside it rather than inside the card. */
/* One height for both halves, set once here and read by everything in
   them, so the mouth and the grid are the same size as each other and the
   panel is the same size whether it holds one, both or neither. Left to
   their natural heights the two drawings came out over 200px on a phone
   and ate the room the definition box needs. */
.dg-abovecard { --above-h: 9.5rem; display: flex; gap: .5rem; margin-bottom: .4rem; }
.dg-abovehalf { flex: 1 1 0; min-width: 0; }
.dg-mouthbox {
  height: 100%; box-sizing: border-box;
  display: flex; flex-direction: column; align-items: center; gap: .15rem;
  background: var(--raised); border: 1px solid var(--edge);
  border-radius: .6rem; padding: .35rem .3rem .3rem;
  color: var(--ink);
}
.dg-mouthimg {
  width: 100%; max-width: 8.5rem; height: auto; display: block;
  /* Scaled to the panel rather than setting it: the drawing gives, the
     box does not. */
  flex: 1 1 auto; min-height: 0; max-height: 100%; object-fit: contain;
}
.dg-mouthimg[hidden] { display: none; }
.dg-mouthcap {
  margin: 0; text-align: center; color: var(--ink-dim);
  font-size: .66rem; line-height: 1.25;
}
@media (hover: hover) { .dg-mouthtoggle:hover { border-color: var(--gold); } }
.dg-mouthtoggle[aria-pressed="false"] { border-color: transparent; }
.dg-mouthtoggle[aria-pressed="true"] { color: var(--ink); border-color: var(--gold); }

/* With a diagram up the card is a quarter shorter, which is where the room
   for it comes from. The card is what gives, never the definition box: the
   rows keep their fixed proportions so the letter does not move as you turn
   cards, and the box above keeps the same five lines it has everywhere
   else. It used to drop to three whenever a panel came up, which meant the
   definition changed shape depending on what else was switched on - the one
   thing a fixed box exists to prevent. */
body.dg-mouth-on .dg-cardmid { grid-template-rows: 1.75rem 4.5rem 2.2rem; }
body.dg-mouth-on .dg-cardface-deva { font-size: 4rem; }
body.dg-mouth-on .dg-cardface-iast { font-size: 2.9rem; }
body.dg-mouth-on .dg-card-flash { min-height: 0; }

/* The way back to the first card, on the last one only. */
.dg-cardrestart {
  flex: 0 0 auto; width: 100%; height: 2.4rem; padding: 0;
  display: flex; align-items: center; justify-content: center;
  background: transparent; border: 0; border-bottom: 1px solid var(--edge);
  color: var(--gold); font-size: 1.15rem; line-height: 1;
  touch-action: manipulation;
}
/* Kept in the layout when it is not offered, so the arrow below it sits in
   the same place on every card and the one press you make over and over
   never moves. */
.dg-cardrestart[hidden] { display: flex; visibility: hidden; }
@media (hover: hover) { .dg-cardrestart:hover { color: var(--gold); } }

/* The corner icon: a miniature of the page with the half it turns on
   filled in, so the button shows where rather than saying it twice. */
.dg-cornerico { display: inline-flex; width: 1.05rem; flex: 0 0 auto; }
.dg-cornerico svg { width: 100%; height: auto; display: block; }
.dg-ci-frame { fill: none; stroke: currentColor; stroke-width: 1.2; opacity: .6; }
.dg-ci-fill { fill: var(--gold); }
/* The grid's third position. Gold says on; green says on, with letters -
   a different colour as well as a different shape, because three states
   are one more than shape alone can carry at this size. */
.dg-cornerico-alt .dg-ci-fill { fill: var(--green); }

/* Both halves keep their box whether or not they have anything in them,
   so turning one off does not move the other or the card below. */
.dg-abovehalf { height: var(--above-h); }
.dg-gridhalf { display: flex; align-items: center; justify-content: center; }

/* The varga table: five places down, and across each row the four stops
   then the nasal. Each row carries its place's colour - the same colour
   that lights up in the mouth beside it. */
.dg-vargabox {
  display: flex; flex-direction: column; gap: 2px; width: 100%;
  /* Square cells, five of them down: held to the panel's height by its
     width, so the table cannot grow taller than the mouth beside it. */
  max-width: var(--above-h); max-height: 100%; box-sizing: border-box;
  background: var(--raised); border: 1px solid var(--edge);
  border-radius: .6rem; padding: .3rem;
}
.dg-vargarow { display: flex; gap: 2px; }
/* A block of its row's colour, faded: the table as a map of places rather
   than a second printing of the alphabet. */
.dg-vargacell {
  flex: 1 1 0; min-width: 0; aspect-ratio: 1 / 1;
  position: relative; border-radius: .18rem;
  background: var(--row, var(--ink-dim)); opacity: .32;
}
/* A gap in the table - a row that is short a letter - reads as absent
   rather than as a place you could be. */
.dg-vargacell[data-empty="1"] { opacity: .07; }
/* You are here. Not a mark laid on top of the square - the square itself,
   lit: full strength, brightened, and outlined so it reads as chosen even
   where its own colour is a pale one. A dot in the middle said the same
   thing twice and covered the colour saying it. */
.dg-vargacell[data-on="1"] {
  opacity: 1; filter: brightness(1.22);
  box-shadow: 0 0 0 1px rgba(255, 255, 255, .8), 0 0 .4rem rgba(255, 255, 255, .3);
}

/* Letters mode: the same map with the alphabet written back onto it. The
   lamp goes - a letter you can read does not need one - and the cell you
   are on inverts instead, which is the strongest mark available without
   covering the thing it is marking. */
.dg-vargabox[data-letters="1"] .dg-vargacell {
  display: flex; align-items: center; justify-content: center;
  font-family: var(--deva); font-size: .74rem; line-height: 1;
  color: var(--ink); background: transparent; opacity: .55;
}
.dg-vargabox[data-letters="1"] .dg-vargacell[data-on="1"] {
  opacity: 1; color: #1c1530; font-weight: 700;
  background: var(--row, var(--gold));
}
.dg-vargabox[data-letters="1"] .dg-vargacell[data-on="1"] { filter: none; }

/* The vowels' table is six rows of four rather than five of five, so its
   cells are not square; the box keeps the height instead. */
.dg-vargabox { height: 100%; }
.dg-vargarow { flex: 1 1 0; min-height: 0; }
.dg-vargacell { aspect-ratio: auto; }

/* The ladder for a letter that is in neither table: one column, the places
   down it, and the one it is made at named. */
.dg-placeladder .dg-laddercell {
  display: flex; align-items: center; justify-content: center;
  font-family: var(--serif); font-size: .6rem; letter-spacing: .02em;
  color: transparent;
}
.dg-placeladder .dg-laddercell[data-on="1"] { color: #1c1530; font-weight: 700; }
.dg-placeladder .dg-vargacell[data-on="1"] { filter: none; }
/* A letter outside the table - a vowel, a sibilant - dims the whole thing
   rather than pretending one of its cells is the answer. */
.dg-vargabox[data-here="0"] { opacity: .45; }

/* With a panel above the card, the definition keeps three lines instead of
   five. Something has to give when two more things are on screen, and a
   definition that scrolls costs less than a card that will not fit. */

/* ------------------------------------------------------------- the tour */

/* Bars, not dots: the dots mean mastery everywhere else, and the screen
   that explains the dots is the worst place to give the shape a second
   meaning. */
.dg-tourhead { margin: 0; }
.dg-tourbar { display: flex; gap: 4px; }
.dg-tourseg {
  flex: 1 1 0; height: 4px; border-radius: 2px;
  background: rgba(255, 241, 217, .14);
}
.dg-tourseg[data-on="1"] { background: var(--gold); }
/* Title and place on one line, the place set small and pushed to the end
   so the title still reads as the heading. */
.dg-tourtitle {
  display: flex; align-items: baseline; gap: .6rem;
  margin: .5rem 0 .1rem;
}
.dg-tourtitle h2 { margin: 0; flex: 1 1 auto; min-width: 0; }
.dg-tourstep {
  flex: 0 0 auto; font-size: .76rem; letter-spacing: .04em;
  text-transform: uppercase; color: var(--ink-dim);
}
.dg-tourbody > p { margin: .55rem 0; }
.dg-tournote { padding: .6rem .8rem; }
.dg-tournote p { margin: .3rem 0; }

/* The card, sized here rather than by the deck screen's full-height
   column: the tour is an ordinary scrolling page and the card is one
   thing on it. */
/* The card as the deck draws it: a face, and the way on down the right
   edge. One frame around both, so the arrow reads as part of the card
   rather than a button parked beside it. */
.dg-tourcardwrap { margin: .7rem 0 .2rem; }
.dg-tourcard {
  display: flex; width: 100%; min-height: 9rem;
  border-radius: 14px; overflow: hidden;
  background: var(--raised); border: 1px solid var(--edge);
}
/* Both columns the same width, so the letter sits in the middle of the
   card rather than shouldered off it by the gold on the right. */
.dg-tourcardback, .dg-tourcardnext { flex: 0 0 3.2rem; }
.dg-tourcardback {
  border: 0; border-right: 1px solid var(--edge);
  background: transparent; color: var(--ink-dim);
  font-size: 1.8rem; line-height: 1; cursor: pointer;
  display: flex; align-items: center; justify-content: center;
}
.dg-tourcardback[disabled] { opacity: .3; cursor: default; }
.dg-tourcardmid {
  flex: 1 1 auto; min-width: 0;
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: .2rem; padding: .8rem .7rem;
  background: transparent; border: 0; color: inherit; font: inherit; cursor: pointer;
}
/* Gold, and the whole column: on the flashcard screen this is the thing to
   press, so it is sized to be pressed rather than aimed at. */
.dg-tourcardnext {
  border: 0; cursor: pointer;
  background: var(--gold); color: var(--ground);
  font-size: 1.8rem; line-height: 1;
  display: flex; align-items: center; justify-content: center;
}
.dg-tourcardnext:active { filter: brightness(.92); }
/* At the end of the four it has nothing left to do, and says so by going
   quiet - which is the same moment the big Next lights up. */
.dg-tourcardnext[disabled] {
  background: var(--raised); color: var(--ink-dim);
  border-left: 1px solid var(--edge); cursor: default;
}
.dg-tourface { font-size: clamp(2.6rem, 14vw, 4rem); line-height: 1.1; }
.dg-tourword { margin: 0; color: var(--brand-green); }
.dg-tourabove { margin: .6rem 0 0; }

/* The row of switches, with the arrow standing under whichever one is
   being talked about. Its place is worked out as a fraction of the row
   rather than measured, so it cannot drift out of step with a reflow. */
/* Room under the row for the arrow and no more. The arrow overlaps the
   button's edge rather than standing clear of it, which is a line of
   height back on the screen that has the least of it - the one with the
   mouth and the chart both open. */
/* Sized for the triangle and, when a switch is owed a second press, the
   word under it. Tight, because the screen it is on is the one with the
   least room: the mouth and the chart are both open below it. */
.dg-toolwrap { margin: .3rem 0 0; padding-bottom: 1.2rem; }
.dg-toolrowwrap { position: relative; }
.dg-tourtools { display: flex; gap: .4rem; }
.dg-tourtools .dg-deckbtn { flex: 1 1 0; justify-content: center; }
.dg-tool-here {
  border-color: var(--gold);
  box-shadow: 0 0 0 2px rgba(220, 193, 81, .3);
}
.dg-toolarrow {
  position: absolute; top: calc(100% - 1px); transform: translateX(-50%);
  display: flex; flex-direction: column; align-items: center;
  color: var(--gold); line-height: 1;
  transition: left .18s ease;
  pointer-events: none;
}
.dg-toolarrow-tip { font-size: 1rem; }
/* Said quietly, under the point of the arrow: a second press is the
   instruction, not a complaint that the first one missed. */
.dg-toolarrow-again {
  font-size: .68rem; letter-spacing: .04em; margin-top: .1rem;
}
/* The card's own box, doing the walkthrough's talking. Held at a steady
   height so the card below it does not jump as the words change, and set
   apart from a meaning only by being a little quieter. */
.dg-toursays { color: var(--ink-dim); }
.dg-tourgloss { min-height: 3em; margin: .1rem 0 .3rem; }

.dg-tourround { margin: .4rem 0 0; }
.dg-tourscore { padding: .7rem .8rem; }
.dg-tourscoreline { margin: 0 0 .3rem; font-size: 1.1rem; color: var(--gold); }
.dg-tourscore button { margin-top: .6rem; }

.dg-tourdots { padding: .6rem .8rem; }
.dg-tourdotrow {
  display: flex; align-items: center; gap: .6rem;
  padding: .22rem 0;
}
.dg-tourstrip {
  display: flex; justify-content: center; gap: .55rem;
  padding: .5rem 0 .2rem;
}
/* The strip is fixed to the foot of the screen where it lives; shown as an
   example it has to sit in the page like anything else. */
.dg-tourstrip .dg-strip {
  position: static; background: none; padding: 0;
}

.dg-tournav { display: flex; gap: .6rem; margin: 1rem 0 .3rem; }
.dg-tournav button { flex: 1 1 0; justify-content: center; }
.dg-tourbtn {
  border-radius: 10px; padding: .55rem .8rem;
  background: transparent; border: 1px solid var(--edge); color: var(--ink);
  font: inherit; cursor: pointer;
}
.dg-tourbtn[disabled] { opacity: .4; cursor: default; }
/* Next waits on the two screens that ask for something first. Dimmed
   rather than hidden: a button that vanishes leaves you wondering where
   the way on went, and one that is plainly not ready yet does not. */
.dg-tournav .dg-primary[disabled] {
  opacity: .35; cursor: default; filter: saturate(.4);
}
.dg-tourend { display: flex; flex-direction: column; gap: .5rem; margin: .8rem 0; }
.dg-tourend button { justify-content: center; }
.dg-homeico { display: inline-flex; width: 1.25rem; flex: 0 0 auto; }
.dg-homeico svg { width: 100%; height: auto; display: block; }
.dg-hm {
  fill: none; stroke: currentColor; stroke-width: 1.2;
  stroke-linecap: round; stroke-linejoin: round;
}
.dg-tourmarks { list-style: none; margin: .5rem 0 .2rem; padding: 0; }
.dg-tourmarks li {
  display: flex; align-items: center; gap: .6rem;
  padding: .2rem 0; border-top: 1px solid var(--edge);
}
.dg-tourmarks li:first-child { border-top: 0; }
.dg-tourmarks .dg-answer { flex: 1 1 auto; color: var(--ink-dim); }
.dg-tourmarks li[data-ok="1"] .dg-mark { color: var(--green); }
.dg-tourmarks li[data-ok="0"] .dg-mark { color: var(--red); }

/*
 * Gold is an instruction, and it is the only one: press this.
 *
 * Never more than one thing at a time wears it - the arrow on the
 * flashcard, the switch the arrow is under, the one live control in the
 * preview of the menu. That is what keeps it from becoming decoration, and
 * it is why nothing in the walkthrough needs a sentence telling somebody
 * where to press next.
 */
.dg-tool-want {
  background: var(--gold); color: var(--ground);
  border-color: var(--gold);
}
/* The row's own rules colour these controls gold; on a gold ground that
   is a button with no label on it, so the text is taken back here. Two
   classes, so it outranks them rather than hoping to come later. */
.dg-tool-want.dg-more, .dg-tool-want.dg-setsbtn, .dg-tool-want.dg-cardsbtn {
  color: var(--ground);
}
.dg-tool-want .dg-ico { color: var(--ground); }
.dg-tool-want .dg-ci-frame { stroke: var(--ground); opacity: .85; }
.dg-tool-want .dg-ci-fill { fill: var(--ground); }

/* The main screen, shown as itself. Inert, and slightly set back from the
   page so it reads as a picture of somewhere rather than somewhere you
   are. */
.dg-tourpreview {
  margin: .6rem 0 .2rem;
  border-radius: 14px; padding: .1rem;
  box-shadow: 0 0 0 1px var(--edge);
}
.dg-tourpreview .dg-menucard { margin: 0; }



/* The answer to the first character, lit like everything else that is
   there to be pressed - and unlit the moment it is, which the round's own
   used flag already knows. */
.dg-opt.dg-tourfirst:not([data-used="1"]) {
  background: var(--gold); border-color: var(--gold);
}
.dg-opt.dg-tourfirst:not([data-used="1"]) .dg-n,
.dg-opt.dg-tourfirst:not([data-used="1"]) .dg-label {
  color: var(--ground);
}

/* The pointer at More. Sits just above the footer, over the button it is
   about, and takes no clicks - what it points at is behind it. */
.dg-moreptr {
  position: absolute; bottom: 100%; transform: translateX(-50%);
  color: var(--gold); font-size: .95rem; line-height: 1;
  padding-bottom: .15rem; pointer-events: none;
}

/* ------------------------------------------------------------- games */

/* Six blocks a page, in columns that slide half a page at a time. */
.dg-gamewindow { overflow: hidden; margin: .6rem -.3rem .2rem; }
.dg-gametrack { display: flex; transition: transform .35s ease; }
.dg-gamecol {
  flex: 0 0 50%; box-sizing: border-box; padding: 0 .3rem;
  display: flex; flex-direction: column; gap: .6rem;
}
/* Back and Next sit where a game's choice buttons do: bottom right, just
   above the menu, at the right edge of the column. The grid keeps room
   below it so the last row of games is never under them. */
.dg-gamepages {
  position: fixed; z-index: 20; margin: 0;
  /* ← More at the left edge of the column, More → at the right. */
  left: max(1rem, calc((100vw - var(--col)) / 2 + 1rem));
  right: max(1rem, calc((100vw - var(--col)) / 2 + 1rem));
  bottom: calc(var(--footh) + var(--sab) + 1.5rem);
  justify-content: space-between; pointer-events: none;
}
.dg-gamepages button { flex: 0 0 auto; min-width: 6.4rem; pointer-events: auto; }
.dg-gamepager { padding-bottom: 3.4rem; }
.dg-gamepages .dg-primary[disabled] { opacity: .35; cursor: default; filter: saturate(.4); }
.dg-gamebtn-learn { border-color: var(--green); }
.dg-gamebtn {
  display: flex; flex-direction: column; gap: .4rem;
  width: 100%; padding: .45rem .45rem .55rem; border-radius: 12px;
  background: var(--raised); border: 1px solid var(--edge);
  color: var(--ink); font: inherit; text-align: left; cursor: pointer;
}
@media (hover: hover) { .dg-gamebtn:hover { border-color: var(--gold); } }
.dg-gamebtn-on { border-color: var(--gold); }
/* What a game trains, as a halo round its block: purple letters, green
   vocabulary, yellow grammar. Two - split on a slant, from 75% across the
   top to 25% across the bottom, the first on the left. */
:root { --dom-l: #b48cff; --dom-v: #7fc98a; --dom-g: #e6c95a; }
.dg-halo { position: relative; border-color: transparent; }
.dg-halo-l { --ha: var(--dom-l); } .dg-halo-v { --ha: var(--dom-v); } .dg-halo-g { --ha: var(--dom-g); }
.dg-halo2-l { --hb: var(--dom-l); } .dg-halo2-v { --hb: var(--dom-v); } .dg-halo2-g { --hb: var(--dom-g); }
.dg-halo::before, .dg-halo::after {
  content: ""; position: absolute; inset: -1px; border-radius: 12px; padding: 2px; pointer-events: none;
  -webkit-mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
  -webkit-mask-composite: xor; mask-composite: exclude;
}
.dg-halo::before { background: var(--ha); }
.dg-halo::after { background: var(--hb); clip-path: polygon(75% 0, 100% 0, 100% 100%, 25% 100%); }
.dg-halo { box-shadow: 0 0 10px -3px var(--ha), 0 0 10px -3px var(--hb); }
.dg-halokey { font-weight: 700; }
.dg-halokey-l { color: var(--dom-l); } .dg-halokey-v { color: var(--dom-v); } .dg-halokey-g { color: var(--dom-g); }
.dg-thumb { display: block; width: 100%; aspect-ratio: 16 / 10; }
.dg-thumb svg { display: block; width: 100%; height: 100%; }
.dg-thumb { position: relative; }
.dg-thumbimg {
  position: absolute; inset: 0; width: 100%; height: 100%;
  object-fit: contain; background: #1b1530; border-radius: 10px;
}
.dg-gamerow { display: flex; align-items: center; justify-content: space-between; gap: .4rem; padding: 0 .15rem; }
.dg-gamename { font-size: .98rem; line-height: 1.2; }
/* A word rather than a colour: the row says it is unfinished to somebody
   reading it, which is what will matter when some of these are out and
   some are not. */
.dg-gameflag {
  flex: 0 0 auto; font-size: .7rem; letter-spacing: .06em;
  text-transform: uppercase; color: var(--ground);
  background: var(--gold); border-radius: 999px; padding: .1rem .45rem;
}
.dg-gamecard { margin-top: .8rem; }
/* Over the page: the request for a game that is not out yet. */
.dg-shade {
  position: fixed; inset: 0; z-index: 60; display: flex; align-items: center; justify-content: center;
  padding: 1rem; background: rgba(12, 9, 24, .72);
}
.dg-askcard { width: 100%; max-width: 26rem; margin: 0; position: relative; padding-top: 2.6rem; }
.dg-askback { position: absolute; top: .5rem; left: .6rem; font-size: 1.4rem; text-decoration: none; }
.dg-asktitle { font-weight: 700; margin: 0 0 .6rem; }
.dg-askcard textarea { min-height: 5rem; }
.dg-askrow { display: flex; align-items: center; gap: .6rem; margin-top: .6rem; }
.dg-askrow .dg-note { flex: 1 1 auto; margin: 0; }
.dg-askrow .dg-primary { margin-left: auto; flex: 0 0 auto; }

/* A page's name with its ? beside it (the practice page). */
.dg-pagetitle { display: flex; align-items: center; justify-content: center; gap: .5rem; margin: .5rem 0 .3rem; }
.dg-pagetitle h2 { margin: 0; }
.dgg-help-btn {
  width: 1.7rem; height: 1.7rem; border-radius: 999px; border: 1.5px solid var(--gold);
  background: transparent; color: var(--gold); font: inherit; font-weight: 700; cursor: pointer; padding: 0;
}
/* Unreleased: seen only by the developer, and marked so. */
.dg-gameflag.dg-gamedev { background: var(--edge); color: var(--ink); }
/* Out to everybody, but still a beta: gold outline rather than gold. */
.dg-gameflag.dg-gamebeta { background: transparent; color: var(--gold); box-shadow: inset 0 0 0 1.5px var(--gold); }

/* The pointer at a row's cards button, placed by measuring it - the rows
   are not a fixed height and the button is not at a fixed offset, so a
   guess would drift the moment a set name wrapped to two lines. */
.dg-tourpreview { position: relative; }
.dg-cardsptr {
  position: absolute; transform: translateX(-50%);
  color: var(--gold); font-size: .95rem; line-height: 1;
  pointer-events: none;
}
.dg-cardsnote { margin-top: .5rem; }

/* Scores as a list of rows that open. A grid rather than a table: the
   numbers line up down their columns either way, and a grid lets a row's
   detail be a block under it instead of a cell that drags the columns
   wider than the screen. */
.dg-statlist { margin-top: .3rem; }
.dg-statrow {
  display: grid; grid-template-columns: 1fr 3.6rem 3.2rem 3.2rem;
  align-items: center; gap: .3rem; width: 100%;
  padding: .45rem .1rem; text-align: left;
  background: none; border: 0; border-top: 1px solid var(--edge);
  color: var(--ink); font: inherit; cursor: pointer;
}
.dg-statlist > .dg-statrow:first-child { border-top: 0; }
.dg-statrow .dg-num { text-align: right; font-variant-numeric: tabular-nums; }
.dg-stathead {
  cursor: default; color: var(--ink-dim); font-size: .82rem;
  padding-bottom: .2rem;
}
.dg-statrow-flat { cursor: default; }
@media (hover: hover) { button.dg-statrow:hover .dg-statname { color: var(--gold); } }
.dg-statname { min-width: 0; }
.dg-statcaret { display: inline-block; width: 1em; color: var(--ink-dim); }
.dg-statrow-flat .dg-statname { padding-left: 1em; }
.dg-stathidden {
  margin-left: .4rem; font-size: .7rem; letter-spacing: .04em;
  text-transform: uppercase; color: var(--ink-dim);
}
.dg-statdetail { padding: .1rem 0 .5rem; }
/* A row still on the menu, and a row put away: the second is still worth
   reading - it is where you go to bring it back - so it dims rather than
   disappears. */
.dg-mblock + .dg-mblock { margin-top: .6rem; border-top: 1px solid var(--edge); padding-top: .5rem; }
.dg-mblock[data-off="1"] .dg-curri { opacity: .45; }

/* The address already leads somewhere. Set apart from the field it was
   typed into, because it is an offer rather than a complaint. */
.dg-taken { margin-top: .6rem; border-color: var(--gold); }
.dg-taken p { margin: .2rem 0 .5rem; }
/* A game's leaderboard, over the game at its end. */
.dgg-boardcard { width: 100%; max-width: 26rem; margin: 0; max-height: calc(100dvh - 2rem); overflow-y: auto; }
.dgg-boardcard h2 { margin: 0 0 .2rem; }
.dg-boardhead .dg-gameflag { vertical-align: middle; margin-left: .3rem; }
/* A set's letters, opened under its row on Progress. */
.dg-bitrow { cursor: pointer; }
.dg-bitcaret { color: var(--ink-dim); font-size: .8em; }
.dg-bits { margin: .15rem 0 .5rem 1.4rem; border-left: 2px solid var(--edge); padding-left: .6rem; }
.dg-bit { display: grid; grid-template-columns: 3.4rem 2.2rem 3.2rem 1fr; align-items: center; gap: .4rem; padding: .18rem 0; }
.dg-bitrun { display: inline-flex; gap: 3px; }
.dg-bitdot { width: 8px; height: 8px; border-radius: 50%; border: 1.5px solid var(--edge); box-sizing: border-box; }
.dg-bitdot.dg-on { background: var(--gold); border-color: var(--gold); }
.dg-bittick { color: var(--green); font-weight: 700; }
.dg-bitdeva { font-family: var(--deva); font-size: 1.25rem; }
.dg-bitiast { color: var(--ink-dim); }
.dg-bitstat { color: var(--ink-dim); font-size: .82rem; text-align: right; white-space: nowrap; }
.dg-bit.dg-known .dg-bitdeva { color: var(--green); }
/* The flashcards bar under the games: half a block high, both columns wide,
   ringed 2/9 yellow, 4/9 purple, 3/9 green - all three domains. */
.dg-learnbar {
  display: flex; align-items: center; gap: .7rem; width: 100%; margin: .5rem 0 0; padding: .45rem .8rem;
  border-radius: 12px; border: 2px solid transparent; color: var(--ink); font: inherit; text-align: left; cursor: pointer;
  background: linear-gradient(var(--raised), var(--raised)) padding-box,
              conic-gradient(from 0deg, var(--dom-g) 0deg 80deg, var(--dom-l) 80deg 240deg, var(--dom-v) 240deg 360deg) border-box;
}
.dg-learnglyph { font-family: var(--deva); font-size: 1.6rem; color: var(--gold); line-height: 1; }
.dg-learntext { display: flex; flex-direction: column; min-width: 0; }
.dg-learnname { font-weight: 700; font-size: .95rem; }
.dg-learnsub { font-size: .8rem; color: var(--ink-dim); }
.dg-learntext { flex: 0 0 auto; line-height: 1.15; }
.dg-learnpics { display: flex; gap: .35rem; margin-left: auto; min-width: 0; overflow: hidden; }
.dg-lt { display: flex; align-items: center; justify-content: center; flex: 0 0 auto; height: 40px; border-radius: 7px; box-sizing: border-box; }
.dg-lt-card { width: 62px; gap: 4px; background: #2b2046; border: 1.5px solid #b9b2cc; }
.dg-lt-akara { font-family: var(--deva); font-size: 1.35rem; color: #f4efe4; line-height: 1; }
.dg-lt-chev { color: #b9b2cc; font-size: .95rem; line-height: 1; }
.dg-lt-mouth { width: 36px; background: #2b2046; border: 1px solid #4a3b86; overflow: hidden; }
.dg-lt-mouth img { height: 36px; width: auto; }
.dg-lt-grid { display: grid; grid-template-columns: repeat(3, 10px); grid-auto-rows: 7px; gap: 2px; align-content: center; align-items: stretch; justify-content: center; width: 42px; padding: 0 3px;
              background: #2b2046; border: 1px solid #4a3b86; }
.dg-lt-cell { border-radius: 2px; }
.dg-lt-cell.dg-lt-on { background: #d9c8ff !important; }
