/* The website reads light: it is where someone decides whether to buy, and
   long-form reading, prices and comparisons belong on white. The player keeps
   its own skin — that is a room you work in, not a page you read.
   `course-home--dark` keeps the dark palette one class away. */
:root {
  --page: #f7fafb;
  --panel: #2f796f;          /* the green the homepage panel and hero share */
  --panel-text: #fffaf2;
  --panel-muted: rgba(255, 249, 240, 0.82);
  --card: #ffffff;
  --line: rgba(1, 106, 130, 0.14);
  --text: #143640;
  --muted: #4a6670;
  --gold: #b9832c;           /* on white the lighter gold stops being readable */
  --teal: #08788b;
}

body.course-home--dark {
  --page: #112226;
  --panel: #1b383f;
  --panel-text: #fff8ee;
  --panel-muted: rgba(255, 248, 238, 0.82);
  --card: rgba(255, 248, 238, 0.07);
  --line: rgba(255, 248, 238, 0.15);
  --text: #fff8ee;
  --muted: rgba(255, 248, 238, 0.66);
  --gold: #e1ad55;
  --teal: #34b8c9;
}

body.course-home--english {
  --panel: #6b4955;
  --gold: #d8a44a;
  --teal: #d8a44a;
}
.practice-entry.is-coming-soon { grid-template-columns: 1fr auto; align-items: center; }
.practice-soon { align-self: center; padding: 9px 18px; border-radius: 999px;
                 border: 1px dashed var(--line); color: var(--muted);
                 font-size: .85rem; font-weight: 600; white-space: nowrap; }

* { box-sizing: border-box; }
body {
  margin: 0;
  min-height: 100vh;
  background: var(--page);
  color: var(--text);
  font-family: 'Montserrat', -apple-system, "Noto Sans TC", system-ui, sans-serif;
  -webkit-font-smoothing: antialiased;
}
a { color: inherit; }
.course-home { width: min(100%, 720px); margin: 0 auto; padding: 22px 18px 40px; }
.course-home__top { display: flex; align-items: center; justify-content: space-between; margin-bottom: 32px; }
.course-home__brand { display: inline-flex; align-items: center; gap: 9px; text-decoration: none; font-weight: 700; }
.course-home__brand img { width: 30px; height: 30px; }
.course-home__account { color: var(--muted); font-size: .84rem; text-decoration: none; }
/* Sits just right of the wordmark rather than opposite it: the brand keeps the
   corner, and the way back reads as a step from it, not as its counterweight. */
.catalog-back { margin-right: auto; padding-left: 22px; color: var(--muted);
                font-size: .84rem; text-decoration: none; }
.catalog-back:hover { color: var(--teal); }

/* Site chrome: the menu bar, contact band and footer the old homepage carried.
   Only the web surfaces get them — an installed app cover (lean) has no use
   for a nav to itself. */
.site-menu { display: flex; gap: 18px; margin-left: auto; margin-right: 18px; }
.site-menu a { color: var(--muted); font-size: .86rem; font-weight: 600; text-decoration: none; white-space: nowrap; }
.site-menu a:hover { color: var(--gold); }
@media (max-width: 620px) {
  .course-home__top { flex-wrap: wrap; gap: 10px; }
  .site-menu { order: 3; width: 100%; margin: 0; gap: 14px; overflow-x: auto; }
}

/* Contact and footer are two full-width bands that meet with no gap: the page
   ends in one move instead of trailing off through a strip of background.
   The green runs a shade deeper at the bottom so the seam against the brown
   reads as two blocks, not one long dark smear. */
.contact-band { margin: 44px calc(50% - 50vw) 0; width: 100vw; box-sizing: border-box;
                padding: 44px 20px 48px; border: 0; border-radius: 0;
                background: linear-gradient(160deg, #2f796f, #1f5350);
                color: #fffaf2; text-align: center; }
.contact-band h2 { margin: 0 0 8px; font-size: 1.35rem; }
.contact-band > p { margin: 0 0 18px; color: rgba(255, 249, 240, .78); font-size: .92rem; }
.contact-band form { display: grid; gap: 10px; width: min(100%, 460px); margin: 0 auto; }
.contact-band input, .contact-band textarea { padding: 12px 14px; border: 1px solid rgba(255, 250, 242, .28); border-radius: 12px; background: rgba(255, 250, 242, .1); color: #fffaf2; font: inherit; }
.contact-band input::placeholder, .contact-band textarea::placeholder { color: rgba(255, 250, 242, .55); }
.contact-band input:focus, .contact-band textarea:focus { outline: none; border-color: #e1ad55; }
/* Sending a message is not the page's main action — the modules are. A
   button sized like the buy button competes with them. */
.contact-band button { width: fit-content; min-width: 150px; margin: 4px auto 0;
                       padding: 11px 26px; border: 0; border-radius: 999px;
                       background: #e1ad55; color: #2a1c08; font: inherit;
                       font-size: .95rem; font-weight: 800; cursor: pointer; }
.contact-band button:hover { background: #ecbb64; }
.contact-band button:disabled { opacity: .6; cursor: default; }
.contact-thanks { margin: 14px 0 0; color: #fffaf2; font-weight: 700; }

/* The same brown band the old homepage ends on: one warm block closes the
   page without competing with the teal surfaces above it. Full-bleed, so it
   reads as the end of the site rather than one more card. */
.site-foot { margin: 0 calc(50% - 50vw); padding: 44px 20px 38px;
             width: 100vw; box-sizing: border-box; background: #5a412f;
             color: rgba(255, 249, 240, .78); text-align: center; }
.site-foot__mark { width: 42px; opacity: .9;
                   filter: drop-shadow(0 5px 7px rgba(23, 33, 31, .28)); }
.site-foot strong { display: block; margin-top: 6px; color: #fffaf2;
                    font-size: 1.35rem; font-weight: 800; letter-spacing: -.035em; }
.site-foot p { margin: 12px auto 22px; max-width: 620px; color: rgba(255, 249, 240, .82);
               font-size: .92rem; line-height: 1.65; }
.site-foot__links { display: flex; flex-wrap: wrap; justify-content: center; gap: 16px; margin-bottom: 12px; }
.site-foot__links a { color: rgba(255, 249, 240, .78); font-size: .82rem; text-decoration: none; }
.site-foot__links a:hover { color: #fffaf2; }
.site-foot small { color: rgba(255, 249, 240, .58); font-size: .76rem; }
/* Section labels are signposts, not accents: gold is reserved for the things
   you can act on (prices, arrows, the CTA). The hero keeps its gold eyebrow —
   that one is the brand moment at the top of the page. */
.course-eyebrow { margin: 0 0 8px; color: var(--muted); font-size: .72rem; font-weight: 700; letter-spacing: .08em; text-transform: uppercase; }
.course-hero { padding: 26px 22px; border: 1px solid rgba(255,250,242,.14); border-radius: 26px;
               background: radial-gradient(circle at 78% 8%, rgba(255,250,242,.10), transparent 18rem), radial-gradient(circle at 18% 20%, rgba(42,121,111,.36), transparent 20rem), linear-gradient(145deg, #2f796f, #245e5b);
               box-shadow: 0 22px 50px rgba(36,94,91,.22); color: var(--panel-text); }
.course-hero .course-eyebrow { color: #e9c887; }
/* The punchline on the green panel, in the brightest gold the page has — the
   same one the CTA is filled with. `--gold` is #b9832c so a price stays
   readable on white, and at h1 size over the hero it went muddy: the half of
   the sentence that is meant to land read quieter than the half above it. */
.course-hero .hero-accent { color: #f0d192; }
body.course-home--dark .course-hero {
  border-color: var(--line);
  background: radial-gradient(circle at 90% 0, rgba(52,184,201,.18), transparent 40%), var(--panel);
  box-shadow: 0 22px 50px rgba(0,0,0,.26);
}
.course-hero h1 { max-width: 560px; margin: 0; font-size: clamp(1.65rem, 6.6vw, 2.65rem); line-height: 1.08; letter-spacing: -.035em; }
.hero-accent { font-style: normal; color: var(--gold); }
/* --panel-muted, not --muted: this text sits ON the panel, and in the light
   theme --muted is a dark grey that vanishes against the green. */
/* A notch above body size: this is the sentence that has to be read, and at
   the inherited 16px it sat below the headline on a phone rather than under
   it. */
.course-hero > p:not(.course-eyebrow) { max-width: 560px; margin: 16px 0 22px; color: var(--panel-muted); font-size: 1.05rem; line-height: 1.65; }
/* Gold, with dark text on it. Gold is the brightest thing on the green panel,
   and dark-on-gold is the readable half of that pairing — white on it sits at
   1.9:1, which washes out on a phone in daylight. */
/* Softer than the amber it was: full width on a dark panel, a saturated gold
   carried more weight than the one thing it is asking for. Lighter reads as an
   invitation; it also lifts the label to 11:1. */
.course-hero__cta { display: flex; justify-content: center; width: 100%; padding: 15px 18px;
                    border-radius: 14px; background: #f0d192; color: #2a1c08;
                    font-weight: 750; text-align: center; text-decoration: none; }
.course-hero__cta:hover { background: #e9c47a; }
.course-hero__note { display: block; margin-top: 9px; color: var(--panel-muted); font-size: .74rem; text-align: center; }
.catalog-head { padding: 6px 2px 0; }
.catalog-head h1 { margin: 0; font-size: clamp(1.6rem, 5.6vw, 2.4rem); line-height: 1.1; letter-spacing: -.03em; }
.course-section { padding: 19px 2px 10px; }
.course-section h1, .course-section h2, .practice-entry h2 { margin: 0; font-size: 1.35rem; line-height: 1.25; }
/* The catalogue on a phone drops the three lines between the heading and the
   modules. They are sales prose, and the numbers in them — every module's
   price — are already printed on the cards themselves. On a wider screen there
   is room to say it, so it stays. */
@media (max-width: 620px) {
  body.catalog .course-note--lead,
  body.catalog .course-note--terms { display: none; }
  body.catalog .language-course-grid { margin-top: 6px; }
}

/* The two lines under the catalogue heading. They were .92rem and .84rem at
   two different weights, which read as two sizes chosen at random rather than
   a sentence and the price under it. Same size now; colour is what separates
   them, and only the number is heavy — 「每門課」 in bold was a blob. */
body.catalog .course-note--lead,
body.catalog .course-note--terms { font-size: .95rem; font-weight: 400; }
body.catalog .course-note--terms strong { font-weight: 700; }
.catalog-head__flag { margin-right: .12em; font-size: .78em; vertical-align: .12em; }

/* ── The account page ─────────────────────────────────────────────────── */
/* No amounts here. Stripe charged the card and emailed the authoritative
   receipt; printing a second number invites the two to disagree. This answers
   what was bought, when, and until when. */
.receipts { display: grid; gap: 8px; margin-top: 14px; }
.receipt { padding: 12px 15px; border: 1px solid var(--line); border-radius: 14px; background: var(--card); }
.receipt strong { display: block; font-size: .9rem; font-weight: 600; }
.receipt small { display: block; margin-top: 3px; color: var(--muted); font-size: .8rem; }
/* Days left is a fact, not an offer — grey until it is nearly out, then gold. */
.language-course__state.is-soon { background: rgba(185,131,44,.12); color: var(--gold); }
.signout { margin: 0; }
.signout button { padding: 7px 16px; border: 1px solid var(--line); border-radius: 999px;
                  background: none; color: var(--muted); font: inherit; font-size: .88rem; cursor: pointer; }
.signout button:hover { color: var(--text); border-color: var(--muted); }
.course-note a { color: var(--teal); }

.catalog-foot { display: flex; justify-content: space-between; gap: 16px;
                margin: 34px 0 8px; padding-top: 18px; border-top: 1px solid var(--line);
                font-size: .85rem; }
.catalog-foot a { color: var(--muted); text-decoration: none; }
.catalog-foot a:hover { color: var(--teal); }

.language-course-grid { display: grid; gap: 10px; margin-top: 17px; }
.language-course-grid > form { display: flex; min-width: 0; margin: 0; }
.language-course { display: flex; align-items: center; gap: 14px; width: 100%; min-height: 84px; padding: 15px 17px; border: 1px solid var(--line); border-radius: 18px; appearance: none; background: var(--card); color: var(--text); cursor: pointer; font: inherit; text-align: left; text-decoration: none; box-shadow: 0 8px 24px rgba(20,54,64,.06); transition: transform .16s ease, border-color .16s ease; }
body.course-home--dark .language-course { box-shadow: none; }
.language-course:hover { transform: translateY(-2px); border-color: var(--gold); }
/* Listed but not purchasable yet: no hover lift, and the state says why.
   `is-static` is the same card shape used to say something rather than to be
   clicked — the three "how it works" cards — so it does not lift either. */
.language-course.is-locked:hover,
.language-course.is-static:hover { transform: none; border-color: var(--line); }
.language-course__side { display: flex; flex-shrink: 0; flex-direction: column; align-items: flex-end; gap: 6px; }
.language-course__price { color: var(--gold); font-size: 1.02rem; font-weight: 800; }
.language-course__price.is-free { color: var(--teal); }
.bundle-teaser { margin: 10px 0 0; font-size: .86rem; }
.bundle-teaser a { color: var(--gold); font-weight: 700; text-decoration: none; }
.bundle-teaser a:hover { text-decoration: underline; }
.bundle-card { display: grid; gap: 16px; margin: 16px 0 6px; padding: 20px 22px;
               border: 1px solid rgba(225,173,85,.38); border-radius: 20px;
               background: linear-gradient(145deg, rgba(225,173,85,.10), rgba(255,248,238,.03)); }
.bundle-card h2 { margin: 0; font-size: 1.2rem; line-height: 1.3; }
.bundle-card__note { margin: 8px 0 0; color: var(--muted); font-size: .86rem; }
.bundle-card__price { margin: 0 0 10px; font-size: 1.05rem; }
.bundle-card__price s { color: var(--muted); margin-right: 8px; }
.bundle-card__price strong { color: var(--gold); font-size: 1.5rem; }
/* What "everything" actually contains. Folded, because the cards above already
   listed each module once — this is for the reader who got as far as the price
   and wants to check what the number covers before paying it. */
.bundle-list { margin-top: 12px; }
.bundle-list > summary { display: inline-flex; align-items: center; gap: 6px;
                         color: var(--gold); font-size: .86rem; font-weight: 700;
                         cursor: pointer; list-style: none; }
.bundle-list > summary::-webkit-details-marker { display: none; }
.bundle-list > summary::after { content: '▾'; font-size: .8em; }
.bundle-list[open] > summary::after { content: '▴'; }
.bundle-list ul { margin: 10px 0 0; padding-left: 18px; color: var(--muted);
                  font-size: .86rem; line-height: 1.8; }
.bundle-list li::marker { color: var(--gold); }
.course-note--terms s { opacity: .55; text-decoration-thickness: 1.5px; }
@media (min-width: 620px) {
  .bundle-card { grid-template-columns: 1fr auto; align-items: center; }
  .bundle-card__buy { min-width: 220px; text-align: right; }
}

/* The offer, read before the checkout. Same panel colour as the player's
   unlock card so the two surfaces are recognisably the same offer. */
/* The offer stays dark on the light site: it is the one moment the page asks
   for money, and a dark card over a dimmed page is where the eye goes. It
   redefines the palette tokens for its own subtree, so every child (eyebrow,
   list markers, scene list) follows without a rule of its own. */
.module-dialog { width: min(94vw, 420px); max-height: 86vh; overflow-y: auto;
                 padding: 24px 22px 26px; border: 1px solid rgba(255,248,238,.15);
                 border-radius: 22px; background: #1b383f;
                 box-shadow: 0 26px 60px rgba(9,20,23,.42);
                 --text: #fff8ee;
                 --muted: rgba(255, 248, 238, 0.66);
                 --gold: #e1ad55;
                 --line: rgba(255, 248, 238, 0.15);
                 color: var(--text); }
.module-dialog::backdrop { background: rgba(9, 20, 23, .62); }
.module-dialog h2 { margin: 0 0 14px; font-size: 1.3rem; }
.module-dialog__close { display: flex; justify-content: flex-end; margin: -8px -6px 0 0; }
.module-dialog__close button { border: 0; background: none; color: var(--muted); font-size: 1.1rem; cursor: pointer; }
.module-dialog__list { margin: 0 0 18px; padding-left: 18px; color: var(--text); line-height: 1.75; font-size: .92rem; }
.module-dialog__list li::marker { color: var(--gold); }
.module-dialog__scenes-label { margin: 0 0 6px; color: var(--muted); font-size: .74rem;
                               font-weight: 700; letter-spacing: .06em; text-transform: uppercase; }
.module-dialog__scenes { margin: 0 0 20px; padding-left: 20px; color: var(--muted);
                         font-size: .86rem; line-height: 1.6; }
.module-dialog__buy { display: block; width: 100%; padding: 13px 18px; border: 0; border-radius: 14px;
                      background: #e1ad55; color: #2a1c08; font: inherit; font-weight: 800;
                      font-size: 1.05rem; text-align: center; text-decoration: none; cursor: pointer; }
.module-dialog__buy:hover { filter: saturate(1.06); }
.language-course.is-owned { border-color: rgba(52,184,201,.45); }
.language-course__state { flex-shrink: 0; align-self: center; padding: 4px 10px; border-radius: 999px; background: #eef3f5; color: var(--muted); font-size: .72rem; white-space: nowrap; }
body.course-home--dark .language-course__state { background: var(--line); }
/* The two states that are not "coming soon" recolour that chip, so they have
   to come AFTER it — same specificity, and while they sat above it the grey
   base won and the teal "已擁有" chip never actually appeared. */
.is-owned-state { background: rgba(52,184,201,.16); color: var(--teal); font-weight: 700; }
/* Ran out, not locked: warm rather than grey, because the card is still an
   offer. Not bold — the label is Chinese, and weight closes the strokes up. */
.is-expired-state { background: rgba(199,124,52,.14); color: #a4620f; }
/* Chip and price side by side. The side column stacks by default, which put
   the price on a second line and made that one row taller than the rest. */
.language-course__side:has(.is-expired-state) { flex-direction: row; align-items: center; gap: 10px; }
.course-note { color: var(--muted); margin-top: 18px; font-size: .84rem; }
/* The lead is the paragraph under a section heading, not a footnote like the
   rest of .course-note — .84rem read as fine print on a phone. */
.course-note--lead { margin: 4px 0 0; font-size: .92rem; line-height: 1.6; }
.course-note--terms { margin: 6px 0 0; color: var(--teal); font-weight: 700; }
.language-course__flag { font-size: 2rem; }
.language-course__body { display: flex; flex: 1; flex-direction: column; gap: 5px; min-width: 0; }
.language-course__body strong { color: var(--text); font-size: 1.04rem; }
.language-course__badge { display: block; width: fit-content; margin-top: 6px; padding: 3px 8px; border-radius: 999px; background: rgba(8,120,139,.11); color: #08788b; font-size: .68rem; font-weight: 800; letter-spacing: .06em; text-transform: uppercase; }
.language-course__body small { color: var(--muted); font-size: .78rem; line-height: 1.35; }
.language-course__scenes { color: var(--teal); font-weight: 700; }
.language-course__arrow { color: var(--gold); font-size: 1.25rem; }
/* ── Ten-second taste ──────────────────────────────────────────────────── */
.taste { display: grid; gap: 18px; margin-top: 18px; padding: 16px;
         border: 1px solid rgba(255,250,242,.12); border-radius: 22px; color: #fff8ee;
         background: radial-gradient(circle at 88% 0, rgba(52,184,201,.20), transparent 46%),
                     linear-gradient(150deg, #23525c, #17383f); }
@media (min-width: 720px) {
  /* Question left, turn right. One column on a phone, where side by side would
     leave both halves too narrow to read. */
  /* Top-aligned, not centred: the question is asked before the turn is taken,
     and centring floated it down beside a card that grows as you answer. */
  /* The card takes the width the panel's own padding used to sit in: this is
     where the turn is taken, and it was the smaller half of a box that was
     mostly margin. The left column keeps just enough for the question. */
  .taste { grid-template-columns: minmax(0, 11rem) minmax(0, 1fr); gap: 18px; padding: 18px; align-items: start; }
}

.taste-eyebrow { margin: 0 0 8px; color: #e9c887; }
.taste-ask h2 { margin: 0 0 10px; font-size: 1.35rem; line-height: 1.25; color: #fff8ee; }
.taste-in { display: block; margin-bottom: 10px; color: rgba(255,248,238,.88); font-size: 1rem; }
.taste-langs { display: flex; gap: 10px; }
/* Big enough to be a target, not a decoration — these are the one thing on the
   left half a visitor is meant to press. */
.taste-langs button { width: 58px; height: 50px; border: 1px solid rgba(255,248,238,.18);
                      border-radius: 14px; background: rgba(255,248,238,.07); font-size: 1.65rem;
                      line-height: 1; cursor: pointer; opacity: .55;
                      transition: opacity .15s, border-color .15s, background-color .15s; }
.taste-langs button.on { opacity: 1; border-color: #e9c887; background: rgba(255,248,238,.14); }

.taste-card { padding: 22px; border: 1px solid rgba(255,248,238,.14); border-radius: 18px;
              background: rgba(255,248,238,.06); }
.taste-prompt { margin: 0; font-size: 1.2rem; font-weight: 600; line-height: 1.45; color: #fff8ee; }

/* Last in the card and centred: whatever else is on screen — the sentence
   alone, or a score and two ways on — the thing you press is in the same place.
   Slim, because it is this card's control and not the page's biggest button. */
.taste-mic { display: flex; margin: 16px auto 0; align-items: center; gap: 9px; padding: 5px 16px 5px 5px;
             border: 0; border-radius: 999px; background: #fbeef0; color: #6d3d49;
             font: inherit; font-size: .9rem; font-weight: 700; cursor: pointer;
             transition: background-color .15s; }
.taste-mic__ring { display: grid; place-items: center; width: 34px; height: 34px;
                   border-radius: 50%; background: #e9b8c2; color: #5c2f3a; }
.taste-mic__ring svg { width: 19px; height: 19px; }
.taste-mic:hover { background: #f7e1e5; }
/* Recording: the ring breathes, so the button says "still listening" without a
   second line of text. */
.taste-mic.is-live .taste-mic__ring { animation: tastePulse 1.2s ease-in-out infinite; }
@keyframes tastePulse {
  0%, 100% { box-shadow: 0 0 0 0 rgba(201, 86, 106, .34); }
  50%      { box-shadow: 0 0 0 9px rgba(201, 86, 106, 0); }
}

/* A class with `display` beats the browser's own [hidden] rule, so these two
   kept their height while empty — which is what made the card look half full. */
.taste-result[hidden] { display: none; }
.taste-result { display: flex; align-items: baseline; flex-wrap: wrap; gap: 4px 14px; margin-top: 16px; }
.taste-score { font-size: clamp(2rem, 6vw, 2.6rem); font-weight: 700;
               line-height: 1; letter-spacing: -.02em; color: #ffd98a; }
.taste-model { flex: 1 1 10rem; font-size: 1rem; line-height: 1.5; color: #fff8ee; }
/* Under the mic and centred with it: after a score the two ways on sit where
   the eye already is, instead of above the button it just came from. */
.taste-after { display: flex; justify-content: center; align-items: center; flex-wrap: wrap;
               gap: 8px 18px; margin-top: 12px; }
.taste-again { padding: 0; border: 0; background: none; color: rgba(255,248,238,.72);
               font: inherit; font-size: .9rem; font-weight: 600; cursor: pointer; }
.taste-again:hover { color: #fff8ee; }
/* Its own row: two lines beside "Next one" would break that row's baseline.
   Centred and sized like an action, not a footnote — after a score this is the
   one link that leads anywhere, and it was the only thing in the card sitting
   left while the mic and "Next one" above it were centred. */
.taste-next { flex: 1 0 100%; margin-top: 4px; color: rgba(255,248,238,.72);
              font-size: .9rem; line-height: 1.5; text-align: center; text-decoration: none; }
/* The course the line came from, at full strength. It used to inherit the
   dimmed colour of the row it sits in, so the one concrete thing on offer was
   the faintest text in the panel. */
.taste-next__course { color: #fff8ee; font-size: 1rem; }
/* Not bold: this is CJK in the Chinese half, and bold CJK is a blob. Colour
   and size carry it instead. */
.taste-next b { display: block; margin-top: 3px; color: #8fe0e8;
                font-size: 1.08rem; font-weight: 400; }
.taste-next:hover b { text-decoration: underline; }
/* The way out is a form now (it posts to checkout), so the button inside has to
   shed everything a button brings with it and read as the same line it was. */
.taste-next-form { flex: 1 0 100%; margin: 0; }
.taste-next-form .taste-next { display: block; width: 100%; padding: 0;
                               border: 0; background: none; cursor: pointer;
                               font: inherit; }

.practice-entry { display: grid; gap: 18px; margin-top: 28px; padding: 22px; border: 1px solid var(--line); border-radius: 22px; background: linear-gradient(135deg, rgba(8,120,139,.07), rgba(255,255,255,.6)); }
body.course-home--dark .practice-entry { background: linear-gradient(135deg, rgba(52,184,201,.10), rgba(255,248,238,.04)); }
.practice-entry p:not(.course-eyebrow) { margin: 9px 0 0; color: var(--muted); font-size: .88rem; line-height: 1.55; }
.practice-entry > a { display: inline-flex; justify-content: center; padding: 13px 16px; border: 1px solid var(--gold); border-radius: 13px; color: var(--gold); font-weight: 700; text-decoration: none; }
footer a { color: var(--muted); font-size: .8rem; text-decoration: none; }
@media (min-width: 620px) {
  .course-home { padding-top: 38px; }
  .language-course-grid { grid-template-columns: repeat(3, 1fr); }
  .language-course-grid > form { height: 100%; }
  .language-course { align-items: flex-start; min-height: 124px; flex-direction: column; }
  .language-course__body { flex: 1; }
  .language-course__arrow { align-self: flex-end; }
  .practice-entry { grid-template-columns: 1fr auto; align-items: center; }
}

/* Installed-app cover: free practice is the second option, not a rival card. */
.practice-entry--compact { display: block; padding: 0; border: 0; background: none; margin-top: 22px; text-align: center; }
.practice-entry--compact h2, .practice-entry--compact p, .practice-entry--compact .course-eyebrow { display: none; }
.practice-entry--compact a { display: inline-block; padding: 0; border: 0; background: none; color: var(--muted); font-size: .88rem; }
.practice-entry--compact a:hover { color: var(--gold); }
