/* ==========================================================================
   Kuhlman Pickleball - video analysis
   Loaded on /video-analysis, /member/video/* and /admin/video/*.
   Tokens come from site.css; nothing here redefines the palette.
   ========================================================================== */

/* ======================================================== 1. public page */

.vid-hero-art {
  position: relative;
  border-radius: var(--radius-lg);
  overflow: hidden;
  background: #000;
  border: 1px solid rgba(255, 255, 255, .16);
  box-shadow: 0 34px 60px -28px rgba(0, 0, 0, .75);
}
.vid-hero-art .frame {
  aspect-ratio: 16 / 10;
  background:
    radial-gradient(120% 90% at 50% 0%, rgba(166, 214, 8, .16), transparent 62%),
    linear-gradient(160deg, #0A3157 0%, #011D3A 58%, #01111F 100%);
  display: flex; align-items: center; justify-content: center;
  position: relative;
}
/* The court, drawn rather than photographed: a real still would be a
   particular student's footage, which is exactly what this feature promises
   not to put on a public page. */
.vid-hero-art .court {
  width: 76%; aspect-ratio: 44 / 20; position: relative;
  border: 2px solid rgba(255, 255, 255, .34); border-radius: 3px;
  transform: perspective(760px) rotateX(46deg);
  background: rgba(166, 214, 8, .07);
}
.vid-hero-art .court::before,
.vid-hero-art .court::after {
  content: ""; position: absolute; left: 0; right: 0; height: 0;
  border-top: 2px dashed rgba(255, 255, 255, .3);
}
.vid-hero-art .court::before { top: 30%; }
.vid-hero-art .court::after  { bottom: 30%; }
.vid-hero-art .net {
  position: absolute; top: 0; bottom: 0; left: 50%; width: 2px;
  background: rgba(255, 255, 255, .55);
}
.vid-hero-art .marker {
  position: absolute; width: 15px; height: 15px; border-radius: 50%;
  background: var(--lime); box-shadow: 0 0 0 6px rgba(166, 214, 8, .26);
}
.vid-hero-art .marker.a { left: 26%; top: 24%; }
.vid-hero-art .marker.b { left: 68%; top: 63%; }

.vid-hero-art .scrub {
  position: absolute; left: 0; right: 0; bottom: 0;
  padding: 14px 18px 16px; background: linear-gradient(transparent, rgba(0, 0, 0, .72) 42%);
}
.vid-hero-art .rail {
  height: 5px; border-radius: 100px; background: rgba(255, 255, 255, .22); position: relative;
}
.vid-hero-art .rail i { position: absolute; inset: 0 62% 0 0; background: var(--lime); border-radius: 100px; }
.vid-hero-art .rail b {
  position: absolute; top: -4px; width: 3px; height: 13px; border-radius: 2px;
  background: var(--cream); box-shadow: 0 0 0 1px rgba(0, 0, 0, .35);
}
.vid-hero-art .stamps { display: flex; gap: 8px; margin-top: 12px; flex-wrap: wrap; }
.vid-hero-art .stamps span {
  font-family: var(--display); font-size: 11.5px; font-weight: 700; letter-spacing: .02em;
  color: var(--navy-900); background: var(--lime); border-radius: 100px; padding: 4px 10px;
}
.vid-hero-art .stamps span.ghost {
  background: rgba(255, 255, 255, .14); color: #D7E4EF;
}

/* ---------------------------------------------------------- how it works */
.vid-steps { counter-reset: vstep; display: grid; grid-template-columns: repeat(3, 1fr); gap: 20px; }
.vid-step {
  background: var(--white); border: 1px solid var(--line); border-radius: var(--radius);
  padding: 26px 24px; position: relative;
}
.vid-step::before {
  counter-increment: vstep; content: counter(vstep);
  display: flex; align-items: center; justify-content: center;
  width: 38px; height: 38px; border-radius: 12px; margin-bottom: 16px;
  background: var(--navy-900); color: var(--lime);
  font-family: var(--display); font-weight: 700; font-size: 1.05rem;
}
.vid-step h3 { font-size: 1.05rem; margin-bottom: 8px; }
.vid-step p { font-size: .93rem; color: var(--body); }

/* ------------------------------------------------------------- the plans */
.vplan {
  display: flex; flex-direction: column; height: 100%;
  border: 1.5px solid var(--line);
}
.vplan.is-popular { border-color: var(--lime-600); box-shadow: 0 0 0 4px rgba(166, 214, 8, .16); }
.vplan .flag {
  position: absolute; top: -12px; left: 24px;
  background: var(--lime); color: var(--navy-900); border-radius: 100px;
  font-family: var(--display); font-size: 11.5px; font-weight: 700;
  letter-spacing: .06em; text-transform: uppercase; padding: 5px 13px;
}
.vplan h3 { font-size: 1.2rem; margin-bottom: 4px; }
.vplan .tagline { font-size: .92rem; color: var(--body); margin-bottom: 18px; }
.vplan .price {
  font-family: var(--display); font-weight: 800; font-size: 2.1rem;
  color: var(--ink); line-height: 1; letter-spacing: -.03em;
}
.vplan .price small { font-size: .82rem; font-weight: 600; color: var(--muted); letter-spacing: 0; margin-left: 6px; }
.vplan .facts {
  display: flex; flex-wrap: wrap; gap: 7px; margin: 16px 0 18px;
  padding-bottom: 18px; border-bottom: 1px solid var(--line);
}
.vplan ul { list-style: none; display: flex; flex-direction: column; gap: 10px; flex: 1; }
.vplan li { display: flex; gap: 10px; align-items: flex-start; font-size: .9rem; color: var(--body); }
.vplan li svg { width: 16px; height: 16px; color: var(--lime-700); flex: none; margin-top: 3px; }
.vplan .go { margin-top: 22px; }

/* ----------------------------------- the worked example ("what you get")
   Not a mockup any more. This is the real player component (.vplayer /
   .vstage / .vrail / .vtools / .vnotes) running the real js/video-review.js
   against one real 30-second rally, so the page cannot advertise behaviour
   the product does not have. Only the framing around it lives here. */
.vdemo {
  display: grid; grid-template-columns: minmax(0, 360px) minmax(0, 1fr); gap: 30px;
  align-items: start;
  background: var(--white); border: 1px solid var(--line);
  border-radius: var(--radius-lg); box-shadow: var(--shadow); padding: 22px;
}
.vdemo-player { min-width: 0; }
/* The clip is portrait, so cap it by height and let the column breathe -
   at full width a 720x1280 phone video would tower over the notes. */
.vdemo-stage video { max-height: 620px; }
.vdemo-notes { min-width: 0; }
.vdemo-head {
  font-size: .78rem; letter-spacing: .09em; text-transform: uppercase;
  color: var(--muted); margin-bottom: 14px;
}

/* site.css sets a global `svg { display: block }`, which is right for artwork
   and wrong for a small icon that belongs on the same line as a heading. Put
   those back on the line, wherever this stylesheet is loaded. */
.panel-head h2 > svg,
.panel-head h3 > svg,
.vid-cardhead > svg,
.vnote-read p > svg,
.faq-item summary span > svg,
.vq-row .side span > svg,
.vq-row .main b > svg,
.vsteps + p > svg,
p.small > svg {
  display: inline-block; vertical-align: -.2em; width: 18px; height: 18px;
}
.faq-item summary span > svg { color: var(--lime-700); }
.vid-cardhead { display: flex; align-items: center; gap: 9px; margin-bottom: 16px; }
.vid-cardhead > svg { flex: none; color: var(--warn); }

/* app.css (which carries .two-col and .checklist) is only loaded in the member
   and admin areas, so the public page brings its own. */
.vid-split { display: grid; grid-template-columns: 1.5fr 1fr; gap: 32px; align-items: start; }
.vid-list { margin: 0; padding-left: 20px; }
.vid-list li { font-size: .93rem; line-height: 1.6; margin-bottom: 10px; color: var(--body); }
.vid-list li:last-child { margin-bottom: 0; }

/* Long marketing headings read better balanced than ragged. */
.vid-balance { text-wrap: balance; }

/* ============================================ 2. the player, shared by all */

.vstage {
  background: #000; border-radius: var(--radius); overflow: hidden;
  border: 1px solid var(--line-2); position: relative;
  /* Centres a clip narrower than the column - see below, portrait footage
     is sized to its own shape rather than stretched into a 16/9 hole. */
  display: flex; align-items: center; justify-content: center;
}
/* Students film on phones, so most footage arriving here is portrait or
   square, not 16/9. This used to be a hard `aspect-ratio: 16 / 9`, which with
   object-fit: contain squeezed a 720x1280 clip into a ~114px-wide strip of
   picture on a phone - unreviewable, and the reason the filming advice used
   to insist on landscape. Letting the element take its own intrinsic size
   inside a max box fits any shape, portrait included. */
.vstage video {
  display: block; width: auto; height: auto;
  max-width: 100%; max-height: 62vh;
  background: #000; object-fit: contain;
}
/* Assets uploaded before their dimensions were recorded carry no width or
   height attribute, so the browser has no intrinsic ratio to lay out with
   until metadata arrives. Keep the old fixed box for those, or the player
   collapses to nothing and then jumps. */
.vstage video:not([width]) {
  width: 100%; aspect-ratio: 16 / 9;
}
.vstage .vstage-empty {
  aspect-ratio: 16 / 9; display: flex; flex-direction: column; gap: 10px;
  align-items: center; justify-content: center; color: #7E93A8; text-align: center; padding: 24px;
}
.vstage .vstage-empty svg { width: 34px; height: 34px; opacity: .7; }

/* Moments rail: every note on this clip, as a tick you can click. Sits under
   the player rather than over the native controls, which stay where the
   browser puts them and keep their own keyboard behaviour. */
.vrail {
  position: relative; height: 30px; margin-top: 10px;
  background: #EEF1F4; border-radius: 8px; overflow: hidden;
}
.vrail-played { position: absolute; left: 0; top: 0; bottom: 0; width: 0; background: rgba(166, 214, 8, .3); }
/* 24px is the WCAG 2.5.8 minimum target, and it applies to a mouse as much as
   to a thumb - this used to be 12px for every pointer that was not coarse.
   The mark itself stays a 3px line; only the hit area grew. */
.vrail-tick {
  position: absolute; top: 0; bottom: 0; width: 24px; margin-left: -12px;
  border: 0; background: transparent; cursor: pointer; padding: 0;
}
.vrail-tick::after {
  content: ""; position: absolute; left: 10.5px; top: 5px; bottom: 5px; width: 3px;
  border-radius: 2px; background: var(--navy-600); transition: transform .12s, background .12s;
}
.vrail-tick:hover::after { transform: scaleX(1.8); background: var(--navy-900); }
.vrail-tick.cat-strength::after { background: var(--ok); }
.vrail-tick.cat-fix::after      { background: #C77D0A; }
.vrail-tick.cat-drill::after    { background: var(--info); }
/* A thumb is blunter than the 24px floor above, so give it a little more. */
@media (pointer: coarse) {
  .vrail-tick { width: 28px; margin-left: -14px; }
  .vrail-tick::after { left: 12.5px; }
}

/* Why a clip is not playing, when it is not. Under the tools rather than over
   the picture, so it never covers the poster of a clip that is merely slow.
   [hidden] has to be restated: display:flex would otherwise beat it. */
.vwarn {
  display: flex; gap: 8px; align-items: flex-start;
  background: var(--warn-bg); color: var(--warn);
  border-radius: var(--radius-sm); padding: 10px 12px; margin-top: 10px;
}
.vwarn[hidden] { display: none; }
.vwarn svg { width: 16px; height: 16px; flex: none; margin-top: 2px; }
.vrail-empty {
  position: absolute; inset: 0; display: flex; align-items: center; justify-content: center;
  /* --muted on #EEF1F4 measures 4.3:1, under AA at this size. */
  font-size: .78rem; color: var(--body);
}

.vtools {
  display: flex; align-items: center; gap: 8px; flex-wrap: wrap;
  margin-top: 12px;
}
.vtools .time {
  font-family: var(--display); font-weight: 700; font-size: .92rem; color: var(--ink);
  font-variant-numeric: tabular-nums; min-width: 96px;
}
.vtools .time small { color: var(--muted); font-weight: 500; }
.vtools .spacer { margin-left: auto; }
.vbtn {
  display: inline-flex; align-items: center; gap: 6px; cursor: pointer;
  border: 1px solid var(--line-2); background: var(--white); color: var(--body);
  font-family: var(--display); font-size: .8rem; font-weight: 600;
  padding: 7px 12px; border-radius: 8px; transition: all .14s;
  /* One of these is an <a> and the rest are <button>s; without this the
     Download link is the only underlined thing in the row. */
  text-decoration: none;
}
.vbtn:hover { border-color: var(--navy-900); color: var(--ink); }
.vbtn.on { background: var(--navy-900); border-color: var(--navy-900); color: var(--lime); }
.vbtn svg { width: 14px; height: 14px; }
.vbtn-mark { background: var(--lime); border-color: var(--lime); color: var(--navy-900); font-size: .86rem; padding: 9px 16px; }
.vbtn-mark:hover { background: #B6E51C; border-color: #B6E51C; color: var(--navy-900); }

/* Clip switcher when a review carries more than one. */
.vclips { display: flex; gap: 8px; flex-wrap: wrap; margin-bottom: 12px; }
.vclip-tab {
  display: flex; align-items: center; gap: 9px; cursor: pointer;
  border: 1.5px solid var(--line); background: var(--white); border-radius: 10px;
  padding: 7px 12px 7px 7px; text-align: left; transition: all .14s;
}
.vclip-tab img, .vclip-tab .ph {
  width: 54px; height: 32px; border-radius: 5px; object-fit: cover; background: var(--navy-800); flex: none;
}
.vclip-tab .ph { display: flex; align-items: center; justify-content: center; color: #7E93A8; }
.vclip-tab .ph svg { width: 15px; height: 15px; }
.vclip-tab b { display: block; font-size: .84rem; color: var(--ink); font-family: var(--display); }
.vclip-tab span { display: block; font-size: .74rem; color: var(--muted); }
.vclip-tab.active { border-color: var(--lime-600); background: var(--lime-50); }

/* ============================================================ 3. the notes */

.vnotes { display: flex; flex-direction: column; gap: 10px; }
.vnote {
  border: 1px solid var(--line); border-left: 4px solid var(--line-2);
  border-radius: var(--radius-sm); background: var(--white); padding: 13px 15px;
  transition: border-color .14s, box-shadow .14s;
}
.vnote:hover { box-shadow: var(--shadow-sm); }
.vnote.cat-strength { border-left-color: var(--ok); }
.vnote.cat-fix      { border-left-color: #C77D0A; }
.vnote.cat-drill    { border-left-color: var(--info); }
.vnote.is-active    { border-color: var(--lime-600); box-shadow: 0 0 0 3px rgba(166, 214, 8, .2); }
.vnote.is-draft     { background: #FBFBF8; border-style: dashed; }

.vnote-top { display: flex; align-items: center; gap: 9px; margin-bottom: 6px; flex-wrap: wrap; }
.vstamp {
  display: inline-flex; align-items: center; gap: 5px; cursor: pointer;
  border: 0; background: var(--navy-900); color: var(--lime);
  font-family: var(--display); font-weight: 700; font-size: .78rem;
  font-variant-numeric: tabular-nums; padding: 4px 10px; border-radius: 6px;
}
.vstamp:hover { background: var(--navy-700); }
.vstamp svg { width: 12px; height: 12px; }
.vnote-top .grow { flex: 1; min-width: 0; }
/* h3 in the member and admin lists; h4 in the public worked example, where
   the section already owns the h2 and the "Key moments" label is the h3. */
.vnote h3, .vnote h4 { font-size: .94rem; line-height: 1.35; }
.vnote p { font-size: .88rem; color: var(--body); margin-top: 5px; white-space: pre-line; }
.vnote-acts { display: flex; gap: 4px; }
.vnote-acts button {
  border: 0; background: transparent; color: var(--muted); cursor: pointer;
  padding: 5px; border-radius: 6px; line-height: 0;
}
.vnote-acts button:hover { background: #F0F2F5; color: var(--ink); }
.vnote-acts button.danger:hover { background: var(--bad-bg); color: var(--bad); }
.vnote-acts svg { width: 15px; height: 15px; }

/* The inline editor the coach types into. */
.vnote-edit { display: none; }
.vnote.editing .vnote-edit { display: block; }
.vnote.editing .vnote-read { display: none; }
.vnote-edit input[type=text], .vnote-edit textarea, .vnote-edit select {
  width: 100%; border: 1px solid var(--line-2); border-radius: 8px;
  padding: 9px 11px; font-size: .9rem; background: var(--white);
}
.vnote-edit textarea { min-height: 74px; resize: vertical; line-height: 1.55; margin-top: 8px; }
.vnote-edit .row { display: flex; gap: 8px; align-items: center; margin-top: 9px; flex-wrap: wrap; }
.vnote-edit .row select { width: auto; min-width: 130px; }
.vnote-edit .row .spacer { margin-left: auto; }
/* The workspace has no Save button, which only works if a failure is loud.
   Anything written here shows; green when it saved, red when it did not. */
.vnote-save {
  font-size: .76rem; color: var(--muted); font-weight: 600;
  opacity: 0; transition: opacity .2s;
}
/* Toggled by the script rather than keyed off :empty - Chrome does not
   reliably re-evaluate :empty when the only change is a text node written
   with textContent, which left a red "not saved" message invisible. */
.vnote-save.show { opacity: 1; }
.vnote-save.on   { color: var(--ok); }
.vnote-save.bad  { color: var(--bad); }

.vnotes-empty {
  border: 1px dashed var(--line-2); border-radius: var(--radius-sm);
  padding: 26px 20px; text-align: center; color: var(--muted); font-size: .9rem;
}

/* Category tally strip on the student's page. */
.vtally { display: flex; gap: 8px; flex-wrap: wrap; }

/* ========================================================= 4. the uploader */

.vdrop {
  border: 2px dashed var(--line-2); border-radius: var(--radius);
  background: var(--cream-50); padding: 34px 24px; text-align: center;
  transition: border-color .16s, background .16s;
}
.vdrop.over { border-color: var(--lime-600); background: var(--lime-50); }
.vdrop .ic {
  width: 52px; height: 52px; border-radius: 15px; margin: 0 auto 14px;
  background: var(--white); border: 1px solid var(--line);
  display: flex; align-items: center; justify-content: center; color: var(--lime-700);
}
.vdrop .ic svg { width: 24px; height: 24px; }
.vdrop h3 { font-size: 1.05rem; margin-bottom: 6px; }
.vdrop p { font-size: .89rem; color: var(--body); max-width: 46ch; margin: 0 auto 16px; }
.vdrop input[type=file] { position: absolute; width: 1px; height: 1px; opacity: 0; pointer-events: none; }
.vdrop.is-full { opacity: 1; }
/* The full state has nothing to drop into, so it shrinks to a line. */
.vdrop-quiet { padding: 14px 18px; border-style: solid; border-width: 1px; background: var(--white); }
.vdrop-quiet p > svg { color: var(--ok); }

.vqueue-list { display: flex; flex-direction: column; gap: 10px; margin-top: 16px; }
.vup {
  display: flex; align-items: center; gap: 13px;
  border: 1px solid var(--line); border-radius: var(--radius-sm);
  background: var(--white); padding: 12px 14px;
}
.vup .main { flex: 1; min-width: 0; }
.vup b { display: block; font-size: .88rem; color: var(--ink); font-family: var(--display);
         overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.vup span { display: block; font-size: .78rem; color: var(--muted); }
.vup .bar { height: 6px; border-radius: 100px; background: #EEF1F4; margin-top: 7px; overflow: hidden; }
.vup .bar i { display: block; height: 100%; width: 0; background: var(--lime); transition: width .25s; }
.vup.done .bar i { background: var(--ok); }
.vup.failed .bar i { background: var(--bad); }
.vup.failed span { color: var(--bad); }
.vup .pct { font-family: var(--display); font-weight: 700; font-size: .84rem;
            color: var(--ink); font-variant-numeric: tabular-nums; min-width: 44px; text-align: right; }

/* A clip already stored, on the draft page. */
.vfile {
  display: flex; align-items: center; gap: 14px;
  border: 1px solid var(--line); border-radius: var(--radius-sm);
  background: var(--white); padding: 12px;
}
.vfile img, .vfile .ph {
  width: 96px; height: 56px; border-radius: 7px; object-fit: cover;
  background: var(--navy-800); flex: none;
}
.vfile .ph { display: flex; align-items: center; justify-content: center; color: #7E93A8; }
.vfile .ph svg { width: 19px; height: 19px; }
.vfile .main { flex: 1; min-width: 0; }
.vfile b { display: block; font-family: var(--display); font-size: .92rem; color: var(--ink);
           overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.vfile .meta { display: flex; gap: 6px; flex-wrap: wrap; margin-top: 5px; }

/* ====================================================== 5. review chrome */

/* The four stages, as a rail the student reads left to right. */
.vsteps { display: flex; align-items: flex-start; gap: 0; }
.vstep-item { flex: 1; text-align: center; position: relative; padding: 0 6px; }
.vstep-item .dot {
  width: 30px; height: 30px; border-radius: 50%; margin: 0 auto 9px;
  display: flex; align-items: center; justify-content: center;
  background: var(--white); border: 2px solid var(--line-2); color: var(--muted);
  font-family: var(--display); font-weight: 700; font-size: .8rem; position: relative; z-index: 2;
}
.vstep-item .dot svg { width: 15px; height: 15px; }
.vstep-item::before {
  content: ""; position: absolute; left: -50%; right: 50%; top: 14px; height: 2px;
  background: var(--line-2); z-index: 1;
}
.vstep-item:first-child::before { display: none; }
.vstep-item.done .dot { background: var(--lime); border-color: var(--lime); color: var(--navy-900); }
.vstep-item.done::before { background: var(--lime); }
.vstep-item.now .dot { background: var(--navy-900); border-color: var(--navy-900); color: var(--lime); }
.vstep-item.now::before { background: var(--lime); }
.vstep-item b { display: block; font-size: .82rem; font-family: var(--display); color: var(--muted); }
.vstep-item.done b, .vstep-item.now b { color: var(--ink); }
.vstep-item span { display: block; font-size: .72rem; color: var(--muted); margin-top: 2px; }

/* The banner at the top of a delivered review. */
.vready {
  background: linear-gradient(135deg, var(--navy-900), var(--navy-700));
  color: #C8D6E4; border-radius: var(--radius); padding: 24px 26px;
  display: flex; gap: 20px; align-items: center; flex-wrap: wrap;
}
.vready h2 { color: #fff; font-size: 1.28rem; margin-bottom: 6px; }
.vready p { color: #AFC2D3; font-size: .93rem; max-width: 58ch; }
.vready .grow { flex: 1; min-width: 240px; }

/* ============================================================ 6. the thread */

.vthread { display: flex; flex-direction: column; gap: 12px; }
.vmsg { display: flex; gap: 11px; align-items: flex-start; }
.vmsg .av {
  width: 34px; height: 34px; border-radius: 50%; flex: none;
  display: flex; align-items: center; justify-content: center;
  font-family: var(--display); font-weight: 700; font-size: .74rem;
  background: #EEF1F4; color: var(--navy-700);
}
.vmsg.coach .av { background: var(--navy-900); color: var(--lime); }
.vmsg .bubble {
  background: var(--white); border: 1px solid var(--line); border-radius: 4px 12px 12px 12px;
  padding: 11px 14px; max-width: 62ch;
}
.vmsg.coach .bubble { background: var(--lime-50); border-color: var(--lime-100); }
.vmsg .bubble p { font-size: .91rem; color: var(--body); white-space: pre-line; }
.vmsg .who { font-size: .74rem; color: var(--muted); margin-bottom: 3px; font-weight: 600; }
.vmsg.unread .bubble { box-shadow: 0 0 0 3px rgba(166, 214, 8, .22); }
.vthread-empty { font-size: .9rem; color: var(--muted); }

/* ======================================================= 7. the admin queue */

.vq { display: flex; flex-direction: column; }
.vq-row {
  display: flex; align-items: center; gap: 14px; padding: 14px 18px;
  border-bottom: 1px solid var(--line); text-decoration: none; color: inherit;
  transition: background .12s;
}
.vq-row:last-child { border-bottom: 0; }
.vq-row:hover { background: #FCFDF7; }
.vq-row .thumb {
  width: 86px; height: 50px; border-radius: 7px; object-fit: cover;
  background: var(--navy-800); flex: none;
}
.vq-row .thumb.ph { display: flex; align-items: center; justify-content: center; color: #7E93A8; }
.vq-row .thumb.ph svg { width: 18px; height: 18px; }
.vq-row .main { flex: 1; min-width: 0; }
.vq-row .main b { display: block; font-family: var(--display); font-size: .95rem; color: var(--ink); }
.vq-row .main .sub { display: block; font-size: .8rem; color: var(--muted); margin-top: 2px; }
.vq-row .tags { display: flex; gap: 6px; flex-wrap: wrap; margin-top: 7px; }
.vq-row .side { text-align: right; flex: none; min-width: 120px; }
.vq-row .side b { display: block; font-size: .84rem; font-family: var(--display); color: var(--ink); }
.vq-row .side span { display: block; font-size: .76rem; color: var(--muted); }
.vq-row.overdue { border-left: 3px solid var(--bad); }
.vq-row.fresh { border-left: 3px solid var(--lime); }

/* The coach's two-column workspace. */
.vwork { display: grid; grid-template-columns: minmax(0, 1.55fr) minmax(320px, 1fr); gap: 20px; align-items: start; }
.vwork-side { position: sticky; top: 88px; max-height: calc(100vh - 108px); overflow-y: auto; }
/* On the student's page the same two-column layout wraps a short, read-only
   list inside a panel, where sticky plus its own scrollbar is friction rather
   than help. */
.vwork-side.vwork-plain { position: static; max-height: none; overflow: visible; }

.vbrief dt { font-size: .74rem; letter-spacing: .07em; text-transform: uppercase; color: var(--muted); font-weight: 700; }
.vbrief dd { font-size: .92rem; color: var(--ink); margin: 3px 0 14px; white-space: pre-line; }
.vbrief dd:last-child { margin-bottom: 0; }

.vkeys { display: flex; flex-wrap: wrap; gap: 6px; }
.vkeys kbd {
  font-family: var(--display); font-size: 11px; font-weight: 700;
  background: var(--white); border: 1px solid var(--line-2); border-bottom-width: 2px;
  border-radius: 5px; padding: 2px 7px; color: var(--ink);
}

/* ============================================================ 8. responsive */

@media (max-width: 1080px) {
  .vwork { grid-template-columns: 1fr; }
  .vwork-side { position: static; max-height: none; }
  /* Stack the example, and stop capping the clip by height once it is no
     longer sharing a row with the notes. */
  .vdemo { grid-template-columns: 1fr; }
  .vdemo-stage video { max-height: 70vh; }
}

@media (max-width: 900px) {
  .vid-steps { grid-template-columns: 1fr; }
  .vid-split { grid-template-columns: 1fr; gap: 24px; }
}

@media (max-width: 720px) {
  .vstage video { max-height: none; }
  /* On a phone the example is the only thing on the row, so let the portrait
     clip take the full column rather than shrinking to satisfy a height cap. */
  .vdemo { padding: 14px; gap: 22px; }
  .vdemo-stage video { max-height: none; }
  .vsteps { flex-wrap: wrap; gap: 14px; }
  .vstep-item { flex: 1 1 44%; }
  .vstep-item::before { display: none; }
  .vq-row { flex-wrap: wrap; }
  .vq-row .side { text-align: left; min-width: 0; width: 100%; }
  .vfile img, .vfile .ph { width: 72px; height: 44px; }
  .vtools .time { min-width: 0; }
  /* Keyboard shortcuts on a phone are noise: there is no keyboard. */
  .vkeys { display: none; }
}

/* Someone who has asked for less motion gets less of it. */
@media (prefers-reduced-motion: reduce) {
  .vup .bar i, .vnote, .vbtn, .vclip-tab, .vrail-tick::after { transition: none; }
}
