  :root {
    --bg: #ffffff;
    --bg-soft: #f5f6f7;
    --panel-dark: #2c3036;
    --panel-darker: #25282d;
    /* Slightly-lighter panel surface — derived from --panel-dark so it follows
       the team's chosen panel color (used by sidebar tab active state, etc.). */
    --panel-accent: color-mix(in srgb, var(--panel-dark) 86%, white);
    --border: #d8dce1;
    --border-soft: #e6e8eb;
    --text: #2c3036;
    --text-dim: #6b7280;
    --red: var(--brand-primary, #7c5cff);   /* follows team brand */
    --danger: #dc2626;                          /* true destructive red */
    --blue: #2864c8;
    --green: #1f9e5a;
    --tool-active: #e23a35;
    /* Team-branded accents. Default to the standard Coachly red/blue and get
       overridden per-team by an inline <style> block in layout.php when the
       active team has a primary/secondary color saved on its profile. */
    --brand-primary: #7c5cff;
    --brand-secondary: #22d3ee;
  }

  /* Dark mode — opt-in via the user's preference toggle on /account.
     A head-inline script in layout.php adds `dark-mode` to <html> BEFORE
     first paint to avoid a bright flash. The body picks up the same
     class on DOM ready (kept in sync by page_account.js when toggled).
     Most surfaces inherit via CSS variables; the rink IMG / canvas
     intentionally stay bright so drill diagrams keep their familiar
     contrast (a dark rink would be illegible). */
  html.dark-mode,
  body.dark-mode {
    --bg: #1a1d22;
    --bg-soft: #232930;
    --border: #3a414a;
    --border-soft: #2c333b;
    --text: #e8eaee;
    --text-dim: #98a0aa;
  }
  /* Surfaces that hardcoded white instead of var(--bg) — flip them in
     dark mode so cards, modals, and dropdowns aren't blinding islands. */
  body.dark-mode .card,
  body.dark-mode .modal,
  body.dark-mode .drill-card,
  body.dark-mode .login-card,
  body.dark-mode .rink-menu,
  body.dark-mode .nav-drawer,
  body.dark-mode .team-menu,
  body.dark-mode .topbar,
  body.dark-mode .canvas-wrap,
  body.dark-mode .sidebar,
  body.dark-mode .toolbar,
  body.dark-mode .line-picker,
  body.dark-mode .drill-tabs,
  body.dark-mode .drill-tab,
  body.dark-mode input[type="text"],
  body.dark-mode input[type="email"],
  body.dark-mode input[type="password"],
  body.dark-mode input[type="number"],
  body.dark-mode select,
  body.dark-mode textarea,
  body.dark-mode .notes-area,
  body.dark-mode .readonly-field {
    background-color: var(--bg-soft);
    color: var(--text);
  }
  body.dark-mode .lp-options { background: var(--bg); }
  body.dark-mode .drill-tab.active { background: var(--bg); }
  * { box-sizing: border-box; }
  html, body {
    margin: 0; padding: 0;
    height: 100%;
    background: var(--bg);
    color: var(--text);
    /* Geist is the new UI body font — cleaner than Roboto and pairs well
     * with Instrument Sans for headlines. The system fallbacks ensure
     * we don't FOIT (flash of invisible text) if Google Fonts is slow.
     * Font-feature-settings turn on the more refined kerning + ligatures
     * that Geist ships with. */
    font-family: 'Geist', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
    -webkit-font-smoothing: antialiased;
    -moz-osx-font-smoothing: grayscale;
    font-feature-settings: 'cv11', 'ss01', 'ss03';
    font-size: 14px;
  }
  body { overflow: auto; }
  body.route-drill { overflow: hidden; }
  .app { display: grid; grid-template-rows: auto 1fr auto; height: 100%; min-width: 0; max-width: 100%; overflow-x: hidden; }
  .footer {
    background: var(--brand-secondary);
    color: white;
    text-align: center;
    padding: 8px 12px;
    font-size: 12px;
    font-weight: 500;
    letter-spacing: 1px;
    text-transform: uppercase;
  }
  .hidden { display: none !important; }

  /* ============ LOGIN SCREEN ============ */
  .login-screen {
    position: fixed; inset: 0;
    background: linear-gradient(135deg, #1c2026 0%, #2c3036 100%);
    display: grid;
    place-items: center;
    z-index: 1000;
  }
  .login-card {
    background: white;
    border-radius: 12px;
    padding: 32px 36px;
    width: 380px;
    max-width: 90vw;
    box-shadow: 0 20px 60px rgba(0,0,0,.4);
    /* Card eases up + fades in on first paint. @starting-style runs
       the moment the element joins the DOM — no JS, no useEffect. */
    transform: translateY(0);
    opacity: 1;
    transition:
      transform 320ms cubic-bezier(0.23, 1, 0.32, 1),
      opacity 280ms ease-out;
  }
  @starting-style {
    .login-card { transform: translateY(8px); opacity: 0; }
  }
  @media (prefers-reduced-motion: reduce) {
    .login-card { transition: opacity 200ms ease-out; transform: none; }
    @starting-style { .login-card { transform: none; } }
  }
  .login-card .logo {
    text-align: center;
    margin-bottom: 24px;
  }
  .login-card .logo .mark {
    width: 64px; height: 64px;
    margin: 0 auto 12px;
    border-radius: 50%;
    background: var(--brand-primary);
    display: grid;
    place-items: center;
    color: white;
    font-weight: 700;
    font-size: 32px;
    overflow: hidden;
  }
  .login-card .logo .mark img {
    width: 100%; height: 100%;
    object-fit: cover;
    display: block;
  }
  .login-card h1 {
    margin: 0;
    font-size: 22px;
    text-align: center;
    color: var(--text);
  }
  .login-card .sub {
    text-align: center;
    color: var(--text-dim);
    margin: 4px 0 24px;
    font-size: 13px;
  }
  .login-tabs {
    display: flex;
    border-bottom: 1px solid var(--border-soft);
    margin-bottom: 18px;
  }
  .login-tab {
    flex: 1;
    text-align: center;
    padding: 10px 0;
    cursor: pointer;
    font-weight: 500;
    color: var(--text-dim);
    border-bottom: 2px solid transparent;
    transition: color 150ms ease-out, border-color 150ms ease-out;
  }
  .login-tab.active {
    color: var(--brand-primary);
    border-bottom-color: var(--brand-primary);
  }
  .login-form input {
    width: 100%;
    border: 1px solid var(--border);
    padding: 10px 12px;
    border-radius: 4px;
    font-family: inherit;
    font-size: 14px;
    margin-bottom: 10px;
    outline: none;
  }
  .login-form input:focus { border-color: var(--blue); }
  .login-form button {
    width: 100%;
    background: var(--brand-primary);
    color: white;
    border: none;
    padding: 11px;
    border-radius: 4px;
    font-family: inherit;
    font-size: 14px;
    font-weight: 500;
    cursor: pointer;
    margin-top: 6px;
    transition: filter .15s;
  }
  .login-form button:hover { filter: brightness(0.92); }
  .login-error {
    color: var(--red);
    font-size: 12px;
    margin-top: 8px;
    min-height: 18px;
  }
  .login-success {
    color: var(--green, #1f9e5a);
    font-size: 13px;
    margin-top: 8px;
    background: #e7f8ee;
    border-radius: 6px;
    padding: 8px 10px;
    line-height: 1.4;
  }
  .login-footer-link {
    text-align: center;
    margin-top: 10px;
    font-size: 12.5px;
  }
  .login-footer-link a {
    color: var(--blue, #2864c8);
    text-decoration: none;
  }
  .login-footer-link a:hover { text-decoration: underline; }
  /* "Continue with Google" button — Google's brand guidance: white
     background, 1px border, the official multi-color G mark, and
     Roboto-ish label. */
  .google-signin-btn {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 10px;
    width: 100%;
    padding: 10px 12px;
    border: 1px solid #dadce0;
    border-radius: 8px;
    background: #fff;
    color: #3c4043;
    font-family: inherit;
    font-size: 14px;
    font-weight: 600;
    cursor: pointer;
    text-decoration: none;
    transition:
      box-shadow 160ms cubic-bezier(0.23, 1, 0.32, 1),
      background 160ms ease-out,
      transform 140ms ease-out;
  }
  .google-signin-btn:hover {
    background: #f8f9fa;
    box-shadow: 0 1px 3px rgba(60,64,67,0.16);
  }
  .google-signin-btn:active {
    transform: scale(0.98);
  }
  .google-signin-btn svg { flex-shrink: 0; }
  .login-divider {
    display: flex;
    align-items: center;
    gap: 10px;
    margin: 14px 0 6px;
    color: var(--text-dim);
    font-size: 11px;
    text-transform: uppercase;
    letter-spacing: 1.5px;
  }
  .login-divider::before,
  .login-divider::after {
    content: '';
    flex: 1;
    height: 1px;
    background: var(--border-soft);
  }
  .login-existing {
    margin-top: 14px;
    padding-top: 14px;
    border-top: 1px solid var(--border-soft);
  }
  .login-existing .label {
    font-size: 11px;
    text-transform: uppercase;
    letter-spacing: 1px;
    color: var(--text-dim);
    margin-bottom: 8px;
  }
  .existing-user {
    padding: 8px 12px;
    border: 1px solid var(--border-soft);
    border-radius: 4px;
    margin-bottom: 6px;
    cursor: pointer;
    display: flex;
    align-items: center;
    justify-content: space-between;
    /* Emil: specific properties, custom ease-out, never `all`. */
    transition:
      background 140ms ease-out,
      border-color 140ms ease-out,
      transform 120ms ease-out;
    /* Stagger entry — each row settles 40ms after the previous. The
       `both` fill-mode keeps the initial offset visible until the
       delay elapses. */
    animation: existing-user-in 220ms cubic-bezier(0.23, 1, 0.32, 1) both;
  }
  @keyframes existing-user-in {
    from { opacity: 0; transform: translateY(4px) scale(0.96); }
    to   { opacity: 1; transform: translateY(0) scale(1); }
  }
  .existing-user:nth-of-type(1) { animation-delay: 40ms; }
  .existing-user:nth-of-type(2) { animation-delay: 80ms; }
  .existing-user:nth-of-type(3) { animation-delay: 120ms; }
  .existing-user:nth-of-type(4) { animation-delay: 160ms; }
  .existing-user:nth-of-type(5) { animation-delay: 200ms; }
  .existing-user:hover { background: var(--bg-soft); border-color: var(--border); }
  /* Press feedback — subtle so the row doesn't feel jumpy. */
  .existing-user:active { transform: scale(0.98); }
  .existing-user .nm { font-weight: 500; }
  .existing-user .del {
    background: transparent;
    border: none;
    color: var(--text-dim);
    cursor: pointer;
    padding: 2px;
    width: auto;
    margin: 0;
    transition: color 140ms ease-out, transform 120ms ease-out;
  }
  .existing-user .del:hover { color: var(--red); background: transparent; }
  .existing-user .del:active { transform: scale(0.92); }
  @media (prefers-reduced-motion: reduce) {
    .existing-user { animation: none; transition: background 120ms ease-out, border-color 120ms ease-out; }
    .existing-user:active,
    .existing-user .del:active { transform: none; }
  }

  /* ============ TOP BAR ============ */
  .topbar {
    /* `!important` is defensive — Ian reported the topbar disappearing on
     * iPad refresh, and we couldn't reproduce in preview. If any future
     * media query / utility-class layer tries to `display: none` this
     * bar, it stays visible. */
    display: flex !important;
    align-items: center;
    gap: 8px;
    padding: 10px 16px;
    background: var(--bg);
    border-bottom: 1px solid var(--border-soft);
    /* Don't push the layout wider than its parent on narrow phones. */
    min-width: 0;
    overflow-x: auto;
    scrollbar-width: none;
    /* Ensure the bar never collapses to zero height (which would look
     * like it had disappeared) — explicit min-height + position:relative
     * keeps it locked in the layout above the canvas. */
    min-height: 48px;
    position: relative;
    z-index: 1;
  }
  .topbar::-webkit-scrollbar { display: none; }
  .topbar-left, .topbar-right {
    display: flex; align-items: center; gap: 8px;
    flex-shrink: 0;
  }
  .topbar-center {
    flex: 1;
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 8px;
    min-width: 0;
  }
  .topbar input[type="text"], .topbar select {
    border: 1px solid var(--border);
    background: #fff;
    padding: 7px 12px;
    border-radius: 4px;
    font-family: inherit;
    font-size: 14px;
    color: var(--text);
    outline: none;
  }
  .topbar input[type="text"]:focus, .topbar select:focus { border-color: var(--blue); }

  /* Topbar grouping + dividers (2026-05-26 visual polish). The center
     bar used to be a flat row of ten icon buttons with no spacing
     hierarchy; we now group them logically and separate the groups
     with thin vertical dividers so the eye can find related actions. */
  .topbar-group {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    flex-shrink: 0;
  }
  .topbar-group--title { gap: 8px; }
  .topbar-divider {
    width: 1px;
    height: 22px;
    background: var(--border-soft);
    margin: 0 4px;
    flex-shrink: 0;
  }

  /* Drill name + Mins styled as a title pair, not generic form inputs.
     Borderless + transparent in the resting state so it reads as the
     active drill's title; hover reveals an outline; focus shows a full
     editing affordance. (2026-05-26) */
  .drill-name {
    width: 320px;
    max-width: 40vw;
    border: 1px solid transparent !important;
    background: transparent !important;
    font-size: 16px !important;
    font-weight: 600 !important;
    color: var(--text);
    padding: 6px 10px !important;
    transition: background .12s, border-color .12s;
  }
  .drill-name::placeholder {
    color: var(--text-dim);
    font-weight: 500;
  }
  .drill-name:hover {
    background: var(--bg-soft) !important;
    border-color: var(--border-soft) !important;
  }
  .drill-name:focus {
    background: white !important;
    border-color: var(--border) !important;
  }
  .mins {
    width: 78px;
    cursor: pointer;
    border: 1px solid transparent !important;
    background: transparent !important;
    color: var(--text-dim);
    font-size: 13px !important;
    padding: 6px 8px !important;
    transition: background .12s, border-color .12s, color .12s;
  }
  .mins:hover {
    background: var(--bg-soft) !important;
    border-color: var(--border-soft) !important;
    color: var(--text);
  }
  .mins:focus {
    background: white !important;
    border-color: var(--border) !important;
    color: var(--text);
  }

  /* Animation button — primary action, gets a brand-coloured fill so
     it stands out from the file/save/output siblings. (2026-05-26) */
  .top-icon-btn--accent {
    background: color-mix(in srgb, var(--brand-secondary) 12%, white);
    color: color-mix(in srgb, var(--brand-secondary) 80%, #000);
  }
  .top-icon-btn--accent:hover {
    background: color-mix(in srgb, var(--brand-secondary) 22%, white);
  }
  .top-icon-btn--accent.active {
    background: var(--brand-secondary) !important;
    color: white !important;
  }
  /* 2026-05-26: rink button moved from topbar-left into the title group
     next to drill-name + mins. Was a dark panel pill; now a light
     borderless button that matches the .mins accessory styling so the
     three elements (Title, Mins, Surface) read as one cohesive
     drill-identity row. */
  .rink-btn {
    background: transparent;
    color: var(--text-dim);
    border: 1px solid transparent;
    padding: 6px 10px;
    border-radius: 6px;
    font-family: inherit;
    font-size: 13px;
    font-weight: 500;
    cursor: pointer;
    display: inline-flex;
    align-items: center;
    gap: 6px;
    position: relative;
    transition: background .12s, border-color .12s, color .12s;
  }
  .rink-btn:hover {
    background: var(--bg-soft);
    border-color: var(--border-soft);
    color: var(--text);
  }
  .rink-btn[aria-expanded="true"],
  .rink-btn.is-open {
    background: var(--bg-soft);
    border-color: var(--border);
    color: var(--text);
  }
  .rink-btn svg { color: var(--text-dim); }
  .rink-btn:hover svg { color: var(--text); }
  .rink-menu {
    /* Fixed so the menu escapes topbar's overflow context (which would
       otherwise clip a dropdown extending below the topbar). Top/left are
       set by JS at toggle time. */
    position: fixed;
    top: 0; left: 0;
    background: white;
    border: 1px solid var(--border);
    border-radius: 6px;
    box-shadow: 0 6px 20px rgba(0,0,0,.15);
    min-width: 230px;
    display: none;
    z-index: 1000;
    padding: 4px;
  }
  .rink-menu.show { display: block; }
  .rink-menu .item {
    display: flex; align-items: center; gap: 10px;
    padding: 6px 10px;
    border-radius: 4px;
    cursor: pointer;
    color: var(--text);
    font-size: 13px;
    transition: background .12s;
    text-align: left;
  }
  .rink-menu .item:hover { background: var(--bg-soft); }
  .rink-menu .item.active { background: var(--bg-soft); font-weight: 500; color: var(--red); }
  .rink-menu .rink-thumb {
    flex: 0 0 auto;
    width: 56px; height: 32px;
    object-fit: contain;
    background: #fff;
    border: 1px solid var(--border-soft);
    border-radius: 3px;
    pointer-events: none;
  }
  .rink-menu .item > span { flex: 1; }
  .top-icon-btn {
    background: transparent;
    border: none;
    color: var(--text);
    padding: 7px 8px;
    cursor: pointer;
    border-radius: 4px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    transition: background .15s;
    position: relative;
    /* iPad/iOS Safari: the topbar has overflow-x: auto, and on touch
     * devices a scroll-vs-tap ambiguity can swallow clicks. Combined with
     * the SVG-absorbs-tap quirk below, the save/print/download icons end
     * up feeling dead. These two properties remove both ambiguities. */
    touch-action: manipulation;
    -webkit-tap-highlight-color: rgba(0, 0, 0, 0.08);
  }
  .top-icon-btn:hover { background: var(--bg-soft); }
  .top-icon-btn svg { width: 18px; height: 18px; pointer-events: none; }
  /* Realism toggle: active state matches the team's brand red so it reads
     as "on" without looking like a destructive action. */
  .top-icon-btn.active {
    background: var(--brand-primary, #7c5cff);
    color: #fff;
  }
  .top-icon-btn.active:hover { background: var(--brand-primary, #7c5cff); filter: brightness(1.05); }
  .top-spacer { width: 6px; }
  .user-chip {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    background: var(--bg-soft);
    padding: 5px 12px 5px 5px;
    border-radius: 20px;
    cursor: pointer;
    transition: background .15s;
  }
  .user-chip:hover { background: #e8eaed; }
  .user-chip .avatar {
    width: 26px; height: 26px;
    border-radius: 50%;
    background: var(--red);
    color: white;
    display: grid;
    place-items: center;
    font-size: 11px;
    font-weight: 700;
  }
  .user-chip .name {
    font-size: 13px;
    font-weight: 500;
    max-width: 100px;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
  }
  .user-menu {
    position: absolute;
    top: 100%; right: 0;
    margin-top: 6px;
    background: white;
    border: 1px solid var(--border);
    border-radius: 6px;
    box-shadow: 0 6px 20px rgba(0,0,0,.15);
    min-width: 180px;
    display: none;
    z-index: 80;
  }
  .user-menu.show { display: block; }
  .user-menu .item {
    padding: 10px 14px;
    cursor: pointer;
    font-size: 13px;
    color: var(--text);
    display: flex;
    align-items: center;
    gap: 8px;
    border-bottom: 1px solid var(--border-soft);
  }
  .user-menu .item:last-child { border-bottom: none; }
  .user-menu .item:hover { background: var(--bg-soft); }
  .user-menu .item.danger { color: var(--red); }
  .user-menu .item svg { width: 14px; height: 14px; }

  /* ============ MAIN ============ */
  main {
    display: grid;
    /* minmax(0, 1fr) lets the middle column shrink below its content's min-content
       size, which is what we want — otherwise the canvas pushes the layout wider
       than the viewport on narrow phones. */
    grid-template-columns: 108px minmax(0, 1fr) 300px;
    /* Row 1 is the drill-tabs strip in the canvas column; the toolbar and
       right sidebar span both rows so their TOOLS / DRILLS headers sit at the
       same vertical level as the tab strip. */
    grid-template-rows: 34px minmax(0, 1fr);
    overflow: hidden;
    min-width: 0;
  }
  main > .toolbar          { grid-column: 1; grid-row: 1 / 3; }
  main > .drill-tabs       { grid-column: 2; grid-row: 1;     }
  main > .canvas-wrap      { grid-column: 2; grid-row: 2;     }
  main > .collapse-strip.left  { grid-column: 1; grid-row: 1 / 3; }
  main > .collapse-strip.right { grid-column: 3; grid-row: 1 / 3; }
  main > .sidebar          { grid-column: 3; grid-row: 1 / 3; }

  /* LEFT TOOLBAR */
  .toolbar {
    background: var(--bg);
    border-right: 1px solid var(--border-soft);
    display: flex;
    flex-direction: column;
    /* Was `overflow: hidden`, which clipped the bottom tools (line-dot,
     * hook, goalie tray) on iPad landscape and on any browser window
     * shorter than ~700px. Now scrolls inside the toolbar when its
     * content is taller than the grid cell. Thin scrollbar so it
     * doesn't eat the narrow 108px column. */
    overflow-x: hidden;
    overflow-y: auto;
    scrollbar-width: thin;
    scrollbar-color: var(--border) transparent;
    /* CSS Grid items default to `min-height: auto`, which expands the
     * item to fit its content — that means overflow-y: auto never has
     * anything to scroll because the toolbar quietly grows past its
     * cell. Pinning min-height: 0 forces it to respect the grid cell
     * height; combined with overflow-y: auto, the bottom tools become
     * reachable via scroll on iPad landscape and short windows. */
    min-height: 0;
    /* Momentum-scroll on iOS Safari (legacy property, still respected
     * by current versions and a no-op elsewhere). Without this, scroll
     * inside the toolbar on iPad feels sticky / snaps back on release. */
    -webkit-overflow-scrolling: touch;
  }
  .toolbar::-webkit-scrollbar { width: 6px; }
  .toolbar::-webkit-scrollbar-track { background: transparent; }
  .toolbar::-webkit-scrollbar-thumb {
    background: var(--border);
    border-radius: 3px;
  }
  .toolbar::-webkit-scrollbar-thumb:hover { background: var(--text-dim); }
  .toolbar-header {
    background: var(--panel-dark);
    color: white;
    padding: 8px 10px;
    font-weight: 700;
    font-size: 12px;
    letter-spacing: 1px;
  }
  /* 2026-05-26 sidebar refactor — three grouped tool sections.
     Originally had "Draw / Players / Equipment" headers above each
     section; Ian asked for those removed in favour of just a thin
     divider between sections (the icon affinity within each group is
     visual enough on its own). The .tool-section-label class is left
     defined below for backwards compat but no longer rendered in the
     drill view. */
  .tool-section {
    padding: 6px 0;
    border-top: 1px solid var(--border-soft);
  }
  .tool-section:first-of-type {
    border-top: none;
    padding-top: 4px;
  }
  .tool-section-label {
    font-size: 10px;
    font-weight: 700;
    letter-spacing: 0.8px;
    text-transform: uppercase;
    color: var(--text-dim);
    padding: 8px 10px 4px;
  }

  .tool-grid {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 4px;
    padding: 4px;
  }
  /* The first .tool-grid keeps overflow-y for legacy reasons (the
     original single-grid layout). With the new sectioned layout the
     parent `.toolbar` owns scroll, so individual grids stay static. */
  .tool {
    aspect-ratio: 1;
    background: #fff;
    border: 1px solid var(--border-soft);
    border-radius: 6px;
    color: var(--text);
    display: flex;
    align-items: center;
    justify-content: center;
    cursor: pointer;
    transition: background .12s, border-color .12s, transform .08s, box-shadow .12s;
    font-family: inherit;
    font-size: 13px;
    font-weight: 500;
    padding: 0;
  }
  .tool:hover {
    background: var(--bg-soft);
    border-color: var(--border);
    transform: translateY(-1px);
  }
  .tool:active { transform: translateY(0); }
  .tool.active {
    background: var(--tool-active);
    border-color: var(--tool-active);
    color: white;
    box-shadow: 0 4px 12px -4px color-mix(in srgb, var(--tool-active) 60%, transparent);
  }
  .tool svg { width: 22px; height: 22px; pointer-events: none; }
  .tool.active svg { stroke: white !important; }
  .tool.active svg [fill="currentColor"] { fill: white; }

  /* Legacy separator (used by the old single-grid layout). Kept so
     plans page tool grids that still emit it don't break visually,
     but it's no longer used in the drill sidebar. */
  .tool-separator {
    grid-column: 1 / -1;
    height: 1px;
    background: var(--border-soft);
    margin: 6px 0;
    border-radius: 0;
  }
  .goalie-section {
    background: var(--panel-dark);
    color: white;
    padding: 12px 16px;
    font-weight: 700;
    font-size: 13px;
    letter-spacing: 1px;
    display: flex;
    align-items: center;
    justify-content: space-between;
    cursor: pointer;
    user-select: none;
    transition: filter .15s;
  }
  .goalie-section:hover, .goalie-section:focus { background: var(--panel-dark); filter: brightness(0.9); }
  .goalie-section svg { transition: transform .25s ease; }
  .goalie-section.collapsed svg { transform: rotate(-90deg); }
  .goalie-grid {
    flex: 0 0 auto;
    max-height: 600px;
    overflow: hidden;
    transition: max-height .3s ease, padding .3s ease;
  }
  .goalie-grid.collapsed {
    max-height: 0;
    padding-top: 0;
    padding-bottom: 0;
  }
  /* Multi-sport: hide the hockey-specific goalie tray for sports that don't
     have hockey-style goalie stamps (basketball, football, etc.). The body
     class is toggled by canvas.js syncGoalieGate() from sports.hasGoalieTools. */
  body:not(.has-goalie-tools) .goalie-section,
  body:not(.has-goalie-tools) .goalie-grid { display: none !important; }
  .player-toolbar {
    padding: 8px 12px;
    display: flex;
    gap: 6px;
    border-bottom: 1px solid var(--border-soft);
  }
  .player-toolbar input {
    flex: 1;
    border: 1px solid var(--border);
    padding: 6px 10px;
    border-radius: 3px;
    font-size: 13px;
    outline: none;
    font-family: inherit;
  }
  .player-toolbar select {
    border: 1px solid var(--border);
    padding: 6px 8px;
    border-radius: 3px;
    font-size: 12px;
    background: white;
    cursor: pointer;
    font-family: inherit;
  }
  .player-list {
    flex: 1;
    overflow-y: auto;
    padding: 4px;
  }
  .player-card {
    background: white;
    border: 1px solid var(--border-soft);
    border-radius: 4px;
    margin-bottom: 6px;
    overflow: hidden;
  }
  .player-card .head {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 10px 12px;
    cursor: pointer;
    transition: background .12s;
  }
  .player-card .head:hover { background: var(--bg-soft); }
  .player-card.expanded .head { border-bottom: 1px solid var(--border-soft); background: var(--bg-soft); }
  .player-jersey {
    background: var(--red);
    color: white;
    width: 32px; height: 32px;
    border-radius: 50%;
    display: grid;
    place-items: center;
    font-weight: 700;
    font-size: 13px;
    flex-shrink: 0;
  }
  .player-jersey.empty { background: var(--text-dim); }
  .player-info { flex: 1; min-width: 0; }
  .player-name {
    font-weight: 500;
    font-size: 14px;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
  }
  .player-meta {
    font-size: 11px;
    color: var(--text-dim);
    margin-top: 2px;
    display: flex;
    gap: 6px;
    align-items: center;
  }
  .player-meta .pos-badge {
    background: var(--blue);
    color: white;
    padding: 1px 6px;
    border-radius: 3px;
    font-weight: 500;
  }
  .player-overall {
    display: flex;
    align-items: center;
    gap: 2px;
    flex-shrink: 0;
  }
  .player-overall .num {
    font-weight: 700;
    color: var(--text);
    font-size: 14px;
  }
  .player-overall .max {
    color: var(--text-dim);
    font-size: 11px;
  }
  .player-card .body { display: none; padding: 10px 12px; background: #fafafa; }
  .player-card.expanded .body { display: block; }
  .rating-row {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 4px 0;
    border-bottom: 1px dashed var(--border-soft);
    font-size: 12px;
  }
  .rating-row:last-child { border-bottom: none; }
  .rating-row .label { color: var(--text); }
  .rating-stars {
    display: flex;
    gap: 1px;
  }
  .rating-stars .star {
    width: 16px; height: 16px;
    cursor: pointer;
    color: #d8dce1;
    transition: color .1s;
  }
  .rating-stars .star.filled { color: #ffb43a; }
  .rating-stars .star:hover { color: #ffb43a; }
  .player-card .notes-block {
    margin-top: 8px;
    padding: 8px;
    background: white;
    border-radius: 3px;
    border-left: 3px solid var(--blue);
    font-size: 12px;
    line-height: 1.45;
  }
  .player-card .notes-block.strength { border-left-color: var(--green); }
  .player-card .notes-block.weakness { border-left-color: #ffb43a; }
  .player-card .notes-block .h {
    font-size: 10px;
    text-transform: uppercase;
    letter-spacing: 1px;
    font-weight: 700;
    color: var(--text-dim);
    margin-bottom: 4px;
  }
  .player-card .actions {
    display: flex;
    gap: 6px;
    margin-top: 10px;
  }
  .player-card .actions button {
    flex: 1;
    background: white;
    border: 1px solid var(--border);
    color: var(--text);
    padding: 5px 10px;
    border-radius: 3px;
    font-size: 12px;
    cursor: pointer;
    font-family: inherit;
  }
  .player-card .actions button:hover { background: white; border-color: var(--blue); color: var(--blue); }

  /* Player rating section in modal */
  #player-ratings {
    border: 1px solid var(--border-soft);
    border-radius: 4px;
    padding: 8px 12px;
    background: var(--bg-soft);
    margin-bottom: 4px;
  }
  #player-ratings .modal-rating-row {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 5px 0;
    border-bottom: 1px dashed var(--border);
    font-size: 13px;
  }
  #player-ratings .modal-rating-row:last-child { border-bottom: none; }
  #player-ratings .rating-stars .star { width: 22px; height: 22px; }

  /* Category management */
  .category-list {
    border: 1px solid var(--border-soft);
    border-radius: 4px;
    overflow: hidden;
    margin-bottom: 14px;
  }
  .category-item {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 8px 12px;
    border-bottom: 1px solid var(--border-soft);
    background: white;
  }
  .category-item:last-child { border-bottom: none; }
  .category-item input {
    border: none;
    outline: none;
    background: transparent;
    font-size: 14px;
    flex: 1;
    margin-right: 8px;
    font-family: inherit;
    padding: 2px 4px;
  }
  .category-item input:focus {
    background: var(--bg-soft);
    border-radius: 3px;
  }
  .category-item button {
    background: transparent;
    border: none;
    cursor: pointer;
    color: var(--text-dim);
    padding: 4px;
    border-radius: 3px;
  }
  .category-item button:hover { color: var(--red); background: var(--bg-soft); }

  /* Drill rating modal list */
  #drill-rating-list {
    border: 1px solid var(--border-soft);
    border-radius: 4px;
    max-height: 50vh;
    overflow-y: auto;
  }
  .drill-rating-item {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 10px 12px;
    border-bottom: 1px solid var(--border-soft);
    background: white;
  }
  .drill-rating-item:last-child { border-bottom: none; }
  .drill-rating-item .player-jersey { width: 26px; height: 26px; font-size: 11px; }
  .drill-rating-item .pname { flex: 1; margin-left: 10px; font-size: 13px; }
  .drill-rating-item .rating-stars .star { width: 20px; height: 20px; }

  .line-picker {
    display: flex;
    align-items: center;
    gap: 10px;
    margin-top: 4px;
    padding: 4px 10px;
    background: var(--bg-soft);
    border: 1px solid var(--border-soft);
    border-radius: 6px;
    overflow-x: auto;
    flex-shrink: 0;
    /* Hide the horizontal scrollbar entirely — its appear/disappear was
       causing the bar to change height and bump the canvas. Users can still
       scroll the bar with trackpad swipe / touch / shift+wheel. */
    scrollbar-width: none;
    -ms-overflow-style: none;
  }
  .line-picker::-webkit-scrollbar { display: none; }
  .line-picker-group {
    display: flex;
    align-items: center;
    gap: 6px;
    flex-shrink: 0;
  }
  .line-picker-divider {
    width: 1px;
    height: 24px;
    background: var(--border);
    flex-shrink: 0;
  }
  .lp-label {
    font-size: 9px;
    font-weight: 700;
    letter-spacing: 0.8px;
    color: var(--text-dim);
    flex-shrink: 0;
  }
  .lp-options {
    display: flex;
    gap: 1px;
    background: white;
    border: 1px solid var(--border-soft);
    border-radius: 4px;
    padding: 1px;
  }
  .lp-btn {
    background: transparent;
    border: none;
    padding: 3px 5px;
    cursor: pointer;
    border-radius: 3px;
    display: flex;
    align-items: center;
    justify-content: center;
    transition: background .12s;
    color: var(--text);
    /* iOS Safari interprets touches inside `overflow-x: auto` containers
     * (the parent `.line-picker`) as potential horizontal-scroll gestures
     * and delays / swallows the click event. `touch-action: manipulation`
     * tells iOS "this is a tap target — don't wait for a scroll to start"
     * so the click fires immediately, which fixes the dead-feeling style
     * buttons reported on iPad. */
    touch-action: manipulation;
    -webkit-tap-highlight-color: rgba(0, 0, 0, 0.08);
    /* Stop iOS Safari from painting its native button gradient/highlight
     * over our explicit background. Without this, after a tap iOS can
     * leave the button looking grey even when the .active class set the
     * red background — making it look like nothing changed. */
    -webkit-appearance: none;
    appearance: none;
  }
  .lp-btn:hover { background: var(--bg-soft); }
  .lp-btn.active {
    background: var(--tool-active);
    color: white;
  }
  .lp-btn svg {
    width: 42px; height: 14px; display: block;
    /* Same iOS fix as the img below: without this, the inline SVG inside
     * the button absorbs the tap on iPad/iOS Safari and the parent
     * button's click handler never fires. With pointer-events: none on
     * the SVG, the touch falls through to the button as expected. */
    pointer-events: none;
  }
  .lp-btn img {
    width: 42px;
    height: 16px;
    object-fit: contain;
    display: block;
    pointer-events: none;
    image-rendering: -webkit-optimize-contrast;
  }
  /* When the button is active (red bg), invert + bump brightness so dark icons
     read as white. Works for the monochrome line previews. */
  .lp-btn.active img { filter: brightness(0) invert(1); }

  /* Inline color swatches inside the style bar */
  .lp-swatches { display: flex; gap: 4px; }
  .lp-swatches .swatch {
    width: 22px; height: 22px;
    border-radius: 50%;
    cursor: pointer;
    border: 2px solid transparent;
    transition: transform .12s, box-shadow .12s;
    padding: 0;
    /* Same iOS-scroll-conflict fix as .lp-btn — colour swatches live in
     * the same overflow-x: auto .line-picker container. */
    touch-action: manipulation;
    -webkit-tap-highlight-color: rgba(0, 0, 0, 0.08);
    /* iOS Safari paints a default gradient/highlight on native buttons.
     * Explicitly opt out so our inline background colour is the only
     * thing showing — otherwise the swatch can look "grey" after tap
     * even when state.color updated correctly. */
    -webkit-appearance: none;
    appearance: none;
  }
  .lp-swatches .swatch:hover { transform: scale(1.1); }
  /* Active swatch: bigger, with both a white inset (so the dot reads
   * clearly against any colour) AND a coloured outer ring (so it's
   * obvious-at-a-glance which colour is currently selected, especially
   * on iPad where users were missing the previous subtle 1px inset). */
  .lp-swatches .swatch.active {
    border-color: var(--blue);
    box-shadow: 0 0 0 1px white inset, 0 0 0 3px rgba(40, 100, 200, 0.55);
    transform: scale(1.15);
  }

  /* Inline size slider */
  .lpg-size input[type=range] {
    width: 110px;
    accent-color: var(--blue);
    margin: 0;
  }
  .lpg-size .size-val {
    font-size: 12px;
    color: var(--text-dim);
    min-width: 22px;
    text-align: right;
  }

  /* Style bar height is fixed — its minimum content (color + size) is always shown
     so the canvas underneath doesn't jump when switching tools. Only the line-style
     and line-ending groups (which don't apply to many tools) get hidden. */
  body[data-tool-kind="none"]  .lpg-style,
  body[data-tool-kind="none"]  .lpg-ending,
  body[data-tool-kind="none"]  .lpd-style,
  body[data-tool-kind="none"]  .lpd-color,
  body[data-tool-kind="shape"] .lpg-style,
  body[data-tool-kind="shape"] .lpg-ending,
  body[data-tool-kind="shape"] .lpd-style,
  body[data-tool-kind="shape"] .lpd-color,
  body[data-tool-kind="text"]  .lpg-style,
  body[data-tool-kind="text"]  .lpg-ending,
  body[data-tool-kind="text"]  .lpd-style,
  body[data-tool-kind="text"]  .lpd-color,
  body[data-tool-kind="stamp"] .lpg-style,
  body[data-tool-kind="stamp"] .lpg-ending,
  body[data-tool-kind="stamp"] .lpd-style,
  body[data-tool-kind="stamp"] .lpd-color { visibility: hidden; }
  body[data-tool-kind="stamp"] .lpg-style,
  body[data-tool-kind="stamp"] .lpg-ending,
  body[data-tool-kind="stamp"] .lpg-size,
  body[data-tool-kind="stamp"] .lpd-style,
  body[data-tool-kind="stamp"] .lpd-size { display: none; }

  /* Position labels (F/C/LW/RW/D/LD/RD/G): same hide list as stamp, plus
     surface the number-badge picker (lpg-pos-num) so a 1-5 badge can be
     toggled on the next-placed label. */
  body[data-tool-kind="position"] .lpg-style,
  body[data-tool-kind="position"] .lpg-ending,
  body[data-tool-kind="position"] .lpd-style,
  body[data-tool-kind="position"] .lpd-color { visibility: hidden; }
  body[data-tool-kind="position"] .lpg-style,
  body[data-tool-kind="position"] .lpg-ending,
  body[data-tool-kind="position"] .lpg-size,
  body[data-tool-kind="position"] .lpd-style,
  body[data-tool-kind="position"] .lpd-size { display: none; }
  /* lpg-pos-num is only shown when the active tool is a position label. */
  body:not([data-tool-kind="position"]) .lpg-pos-num,
  body:not([data-tool-kind="position"]) .lpd-pos-num { display: none; }
  .pos-num-btn {
    width: 32px; height: 28px;
    padding: 2px;
    color: #111;
  }
  .pos-num-btn svg { width: 100%; height: 100%; display: block; }
  .pos-num-btn.active { color: var(--red, #7c5cff); }
  /* The number badge (the "1/2/3/4/5" outside the white circle) uses
     currentColor by default — which in the active state becomes red and
     vanishes against the red button background. Force it to white when
     active so it stays legible. The inner letter + circle stroke stay red
     because they sit on the white circle fill and are perfectly readable
     there. */
  .pos-num-btn.active .pos-num-badge { fill: white; }

  /* Line context menu */
  .line-ctx-menu {
    position: fixed;
    background: white;
    border: 1px solid var(--border);
    border-radius: 6px;
    box-shadow: 0 8px 24px rgba(0,0,0,.18);
    padding: 6px;
    min-width: 200px;
    display: none;
    z-index: 90;
    font-size: 13px;
  }
  .line-ctx-menu.show { display: block; }
  .line-ctx-section {
    padding: 4px 6px;
    font-size: 10px;
    font-weight: 700;
    letter-spacing: 1px;
    color: var(--text-dim);
    border-bottom: 1px solid var(--border-soft);
    margin-bottom: 4px;
  }
  .line-ctx-row {
    display: flex;
    gap: 2px;
    margin-bottom: 4px;
    flex-wrap: wrap;
  }
  .line-ctx-row .lp-btn { padding: 4px; border: 1px solid var(--border-soft); }
  .line-ctx-delete {
    width: 100%;
    margin-top: 6px;
    background: white;
    border: 1px solid var(--border);
    color: var(--red);
    padding: 6px;
    border-radius: 3px;
    cursor: pointer;
    font-family: inherit;
    font-size: 13px;
  }
  .line-ctx-delete:hover { background: #fff0f0; }

  .player-label { font-weight: 700; font-size: 13px; line-height: 1; }
  .player-label .sub { font-size: 9px; font-weight: 700; vertical-align: super; }

  /* CANVAS */
  .canvas-wrap {
    background: var(--bg);
    display: flex;
    flex-direction: column;
    overflow: hidden;
    padding: 6px 10px 8px;
  }
  .canvas-stage {
    flex: 1;
    display: grid;
    place-items: center;
    min-height: 0;
    position: relative;
  }
  .canvas-frame {
    position: relative;
    background: white;
    overflow: visible; /* explicit — child canvases extend outside before CSS-rotate */
    /* Force 3D compositing on the frame so child canvas transforms are
       processed as part of the 3D layer pipeline instead of the 2D
       paint-then-transform pipeline. iOS Safari + some Blink versions
       are flaky when 2D-transforming a canvas with a heavy bitmap. */
    transform-style: preserve-3d;
    -webkit-transform-style: preserve-3d;
    /* width/height set by fitCanvas() in rink.js to fit the stage while preserving rink aspect */
  }
  .canvas-frame > * {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    display: block;
  }
  #rink-image { object-fit: fill; user-select: none; pointer-events: none; }
  #rink { pointer-events: none; }
  #drawing { cursor: crosshair; touch-action: none; }
  /* Team logo at center ice (full rink only). Faded so it never competes with
     the drill overlay. Sized as a fraction of the frame so it tracks any rink-fit. */
  #rink-team-logo {
    inset: auto;
    top: 50%; left: 50%;
    width: 22%; height: 24%;
    transform: translate(-50%, -50%);
    object-fit: contain;
    opacity: 0.16;
    pointer-events: none;
    user-select: none;
  }
  /* `.canvas-frame > *` above sets `display: block` and outweighs the
     UA `[hidden] { display: none }` rule (class+universal vs attribute
     selector), so rink.js setting `logoEl.hidden = true` for half-rink /
     no-logo teams was failing — an empty `<img src="">` rendered as the
     broken-image icon at center ice. Belt-and-suspenders: respect both
     [hidden] and an empty src. (Ian: "there is a broken image on the
     surface ... custom image") */
  #rink-team-logo[hidden],
  #rink-team-logo:not([src]),
  #rink-team-logo[src=""] { display: none; }

  /* Animation playback overlay */
  /* --------------------------------------------------------------
     ANIMATION EDITOR PANEL  (replaces .line-picker when anim mode is on)
     --------------------------------------------------------------
     Sibling of .canvas-stage / .line-picker inside .canvas-wrap. When
     body.anim-active is set, the line-picker hides and #anim-panel
     takes its slot. The panel hosts: a toolbar row (play / loop /
     speed / add / dup / delete / counter / close) and a horizontal
     thumbnail strip (#anim-timeline) of frame chips.

     Re-uses the route-schedule's --rb-* tokens (defined elsewhere) so
     the panel matches the rest of the redesigned chrome.
  */
  /* Style bar STAYS visible during animation mode — coaches still need to
   * change line styles / endings / colours / position numbers while editing
   * a frame. The anim-panel just stacks below it. */
  body.route-drill .anim-panel.hidden { display: none; }
  .anim-panel {
    display: flex;
    flex-direction: column;
    gap: 8px;
    margin-top: 4px;
    padding: 8px 10px;
    background: var(--bg-soft);
    border: 1px solid var(--border-soft);
    border-radius: 8px;
    flex-shrink: 0;
    --rb-ice:      #1e6fbf;
    --rb-ice-soft: rgba(30, 111, 191, 0.10);
    --rb-ice-glow: rgba(30, 111, 191, 0.20);
    --rb-loss:     #d94929;
    --rb-loss-soft:rgba(217, 73, 41, 0.08);
    --rb-warm:     #e89043;
  }

  /* Toolbar row */
  .anim-toolbar {
    display: flex;
    align-items: center;
    gap: 6px;
    flex-wrap: wrap;
  }
  .anim-btn {
    display: inline-flex;
    align-items: center;
    gap: 5px;
    padding: 6px 10px;
    background: white;
    border: 1px solid var(--border-soft);
    border-radius: 6px;
    color: var(--text);
    font-family: inherit;
    font-size: 13px;
    font-weight: 500;
    cursor: pointer;
    transition: background-color .12s, border-color .12s, color .12s;
    -webkit-appearance: none;
    appearance: none;
  }
  .anim-btn:hover { background: var(--bg-soft); border-color: var(--border); }
  .anim-btn svg { width: 14px; height: 14px; }
  .anim-btn-label { font-size: 12px; }
  .anim-btn.primary {
    background: var(--rb-ice);
    color: white;
    border-color: var(--rb-ice);
    /* Slightly chunkier so the play button reads as the anchor of the bar. */
    padding: 8px 12px;
  }
  .anim-btn.primary:hover { background: #1759a3; border-color: #1759a3; }
  .anim-btn.primary svg { width: 16px; height: 16px; }
  .anim-btn.danger { color: var(--rb-loss); border-color: rgba(217, 73, 41, 0.30); }
  .anim-btn.danger:hover { background: var(--rb-loss-soft); border-color: var(--rb-loss); }
  .anim-btn.anim-toggle.active {
    background: var(--rb-ice);
    color: white;
    border-color: var(--rb-ice);
  }
  .anim-btn.anim-toggle.active:hover { background: #1759a3; border-color: #1759a3; }

  .anim-speed {
    background: white;
    border: 1px solid var(--border-soft);
    border-radius: 6px;
    padding: 6px 8px;
    font-family: inherit;
    font-size: 12px;
    font-weight: 600;
    color: var(--text);
    cursor: pointer;
    -webkit-appearance: none;
    appearance: none;
    /* Custom chevron — keeps it consistent across iOS / desktop. */
    background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%2398a0aa' stroke-width='2.4' stroke-linecap='round' stroke-linejoin='round'><polyline points='6 9 12 15 18 9'/></svg>");
    background-repeat: no-repeat;
    background-position: right 6px center;
    background-size: 10px 10px;
    padding-right: 22px;
  }
  .anim-divider {
    width: 1px;
    height: 22px;
    background: var(--border);
    margin: 0 2px;
  }
  .anim-spacer { flex: 1; }
  .anim-counter {
    font-family: inherit;
    font-size: 12px;
    color: var(--text-dim);
    padding: 0 6px;
  }

  /* Per-frame duration input — how many seconds this frame holds before
   * playback transitions to the next frame. Compact "Time [ 1.0 ] s" layout. */
  .anim-duration-label {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    padding: 4px 8px;
    background: white;
    border: 1px solid var(--border-soft);
    border-radius: 6px;
    font-family: inherit;
    font-size: 11px;
    color: var(--text-dim);
    cursor: text;
  }
  .anim-duration-text { letter-spacing: 0.05em; }
  .anim-duration {
    width: 44px;
    background: transparent;
    border: none;
    padding: 0;
    margin: 0;
    font-family: inherit;
    font-size: 13px;
    font-weight: 600;
    color: var(--text);
    text-align: right;
    -moz-appearance: textfield;
  }
  .anim-duration::-webkit-outer-spin-button,
  .anim-duration::-webkit-inner-spin-button {
    -webkit-appearance: none;
    margin: 0;
  }
  .anim-duration:focus { outline: none; }
  .anim-duration-label:focus-within {
    border-color: var(--rb-ice);
    box-shadow: 0 0 0 3px rgba(30, 111, 191, 0.12);
  }
  .anim-duration-unit { color: var(--text-dim); }

  /* Timeline strip — horizontal scrollable list of frame thumbnails */
  .anim-timeline {
    display: flex;
    align-items: center;
    gap: 8px;
    overflow-x: auto;
    padding: 4px 2px;
    scrollbar-width: thin;
    scrollbar-color: var(--border) transparent;
    -webkit-overflow-scrolling: touch;
  }
  .anim-timeline::-webkit-scrollbar { height: 6px; }
  .anim-timeline::-webkit-scrollbar-track { background: transparent; }
  .anim-timeline::-webkit-scrollbar-thumb { background: var(--border); border-radius: 3px; }

  .anim-chip {
    position: relative;
    display: inline-flex;
    align-items: flex-end;
    justify-content: flex-start;
    width: 88px;
    height: 56px;
    padding: 0;
    border: 2px solid var(--border-soft);
    border-radius: 7px;
    background: white;
    cursor: pointer;
    flex-shrink: 0;
    transition: border-color .12s, transform .12s, box-shadow .12s;
    overflow: hidden;
    -webkit-appearance: none;
    appearance: none;
    -webkit-tap-highlight-color: rgba(0, 0, 0, 0.08);
  }
  .anim-chip:hover { border-color: var(--border); transform: translateY(-1px); }
  .anim-chip.active {
    border-color: var(--rb-ice);
    box-shadow: 0 0 0 3px var(--rb-ice-soft);
    transform: translateY(-1px);
  }
  .anim-chip-thumb {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    object-fit: contain;
    object-position: center;
    pointer-events: none;
  }
  .anim-chip-num {
    position: relative;
    z-index: 1;
    padding: 1px 5px;
    margin: 4px;
    background: rgba(255, 255, 255, 0.92);
    border-radius: 4px;
    font-family: inherit;
    font-size: 10px;
    font-weight: 700;
    color: var(--text);
    line-height: 1.2;
    box-shadow: 0 1px 2px rgba(0, 0, 0, 0.08);
  }
  .anim-chip.active .anim-chip-num {
    background: var(--rb-ice);
    color: white;
  }
  .anim-chip-add {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 48px;
    height: 56px;
    border: 2px dashed var(--border);
    border-radius: 7px;
    background: transparent;
    color: var(--text-dim);
    cursor: pointer;
    flex-shrink: 0;
    transition: border-color .12s, color .12s, background-color .12s;
    -webkit-appearance: none;
    appearance: none;
  }
  .anim-chip-add svg { width: 20px; height: 20px; }
  .anim-chip-add:hover {
    border-color: var(--rb-ice);
    color: var(--rb-ice);
    background: var(--rb-ice-soft);
  }

  /* Primary "Add frame" — the carry-forward next-moment action. Ice-tinted so
     the main animate move stands out from the toggle buttons beside it. */
  .anim-btn.primary-add {
    background: var(--rb-ice-soft);
    border-color: var(--rb-ice);
    color: var(--rb-ice);
    font-weight: 600;
  }
  .anim-btn.primary-add:hover { background: var(--rb-ice); color: #fff; border-color: var(--rb-ice); }

  /* Record toggle — red (the recording metaphor) when active, overriding the
     default ice-blue .anim-toggle.active. */
  #anim-record-btn.anim-toggle.active { background: var(--rb-loss); border-color: var(--rb-loss); color: #fff; }
  #anim-record-btn.anim-toggle.active:hover { background: #c23e1f; border-color: #c23e1f; }
  /* While recording, frame the rink so the coach knows drags now add frames. */
  body.anim-record .canvas-stage { outline: 2px solid rgba(217, 73, 41, 0.55); outline-offset: -3px; }

  /* Guided empty-state hint — visible only while a single frame exists. */
  .anim-hint {
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 8px 12px;
    background: var(--rb-ice-soft);
    border: 1px solid var(--rb-ice-glow);
    border-radius: 8px;
    color: var(--text);
    font-size: 12.5px;
    line-height: 1.45;
    /* The anim-panel centers/shrink-wraps its column children. width:100%
       (not align-self:stretch) pins to the panel's definite width on BOTH
       desktop and mobile — stretch would resolve to the toolbar's max-content
       width on the mobile scrolling row and overflow the viewport. */
    width: 100%;
    min-width: 0;
    box-sizing: border-box;
  }
  .anim-hint[hidden] { display: none; }
  .anim-hint > svg { width: 18px; height: 18px; color: var(--rb-ice); flex-shrink: 0; }
  .anim-hint-step {
    display: inline-flex; align-items: center; justify-content: center;
    width: 16px; height: 16px; margin-right: 2px;
    background: var(--rb-ice); color: #fff; border-radius: 50%;
    font-size: 10px; font-weight: 700; line-height: 1;
  }
  .anim-hint-tip { color: var(--text-dim); font-style: italic; }
  .anim-hint-close {
    appearance: none; border: none; background: transparent; color: var(--text-dim);
    width: 28px; height: 28px; margin-left: auto; flex-shrink: 0; border-radius: 6px; cursor: pointer;
    display: inline-grid; place-items: center; padding: 0; align-self: flex-start;
  }
  .anim-hint-close svg { width: 14px; height: 14px; }
  .anim-hint-close:hover { background: rgba(0, 0, 0, 0.06); color: var(--text); }
  .anim-hint-close:focus-visible { outline: 2px solid var(--brand-primary); outline-offset: 1px; }

  /* Timeline scrubber — draggable playhead across the whole motion. */
  .anim-scrub {
    padding: 2px 4px 0;
    /* width:100% (not align-self:stretch) — see .anim-hint. Pins to the panel's
       definite width so the track can't overflow the mobile scrolling toolbar. */
    width: 100%;
    min-width: 0;
    box-sizing: border-box;
  }
  .anim-scrub[hidden] { display: none; }
  .anim-scrub-track {
    position: relative;
    width: 100%;
    height: 22px;
    cursor: pointer;
    touch-action: none;        /* pointer drag scrubs instead of scrolling */
  }
  .anim-scrub-rail {
    position: absolute; left: 0; right: 0; top: 50%;
    height: 4px; transform: translateY(-50%);
    background: var(--border-soft); border-radius: 3px;
  }
  .anim-scrub-fill {
    position: absolute; left: 0; top: 50%; width: 0;
    height: 4px; transform: translateY(-50%);
    background: var(--rb-ice); border-radius: 3px; pointer-events: none;
  }
  .anim-scrub-ticks { position: absolute; inset: 0; pointer-events: none; }
  .anim-scrub-key {
    position: absolute; top: 50%; width: 2px; height: 10px;
    transform: translate(-50%, -50%);
    background: var(--text-dim); opacity: .5; border-radius: 1px;
  }
  .anim-scrub-head {
    position: absolute; top: 50%; left: 0; width: 14px; height: 14px;
    transform: translate(-50%, -50%);
    background: #fff; border: 2px solid var(--rb-ice); border-radius: 50%;
    box-shadow: 0 1px 3px rgba(0, 0, 0, 0.2); pointer-events: none;
    transition: box-shadow .12s;
  }
  body.anim-scrubbing .anim-scrub-head { box-shadow: 0 0 0 4px var(--rb-ice-soft), 0 1px 3px rgba(0, 0, 0, 0.2); }

  /* "More" overflow popover — declutters the toolbar by holding the secondary
     controls (onion / hide-on-play / speed / frame-time / blank frame /
     export). The menu is portaled to <body>, so it lives OUTSIDE .anim-panel
     and can't see the panel-scoped --rb-* tokens — use literal ice #1e6fbf. */
  .anim-more { position: relative; display: inline-flex; }
  .anim-more-menu {
    display: flex;
    flex-direction: column;
    gap: 2px;
    min-width: 224px;
    max-width: 88vw;
    padding: 8px;
    background: #fff;
    border: 1px solid var(--border);
    border-radius: 10px;
    box-shadow: 0 12px 34px rgba(0, 0, 0, 0.18);
  }
  .anim-more-menu--portal { position: fixed; z-index: 1000; max-height: calc(100vh - 16px); overflow-y: auto; }
  .anim-more-menu[hidden] { display: none; }
  /* Moved buttons render as full-width left-aligned rows; labels always show
     (the toolbar hides them on mobile, but the menu should read as text). */
  .anim-more-menu .anim-btn {
    width: 100%;
    justify-content: flex-start;
    background: transparent;
    border-color: transparent;
    padding: 8px 10px;
  }
  .anim-more-menu .anim-btn:hover { background: var(--bg-soft); border-color: var(--border-soft); }
  .anim-more-menu .anim-btn-label { display: inline !important; font-size: 13px; }
  .anim-more-menu .anim-btn svg { width: 16px; height: 16px; flex-shrink: 0; }
  .anim-more-menu .anim-btn.anim-toggle.active {
    background: #1e6fbf; color: #fff; border-color: #1e6fbf;
  }
  .anim-more-menu .anim-btn.anim-toggle.active:hover { background: #1759a3; border-color: #1759a3; }
  /* Label + control rows (Speed, Frame time). */
  .anim-more-row {
    display: flex; align-items: center; justify-content: space-between;
    gap: 10px; padding: 6px 10px;
  }
  .anim-more-row-label { font-size: 13px; color: var(--text); font-weight: 500; }
  .anim-more-row .anim-duration-label { margin: 0; }
  .anim-more-sep { height: 1px; background: var(--border-soft); margin: 5px 4px; }
  /* Export group fills the row inside the menu. */
  .anim-more-menu .anim-export-group { display: flex; width: 100%; }
  .anim-more-menu .anim-export-main { flex: 1; }
  .anim-more-menu .anim-export-caret { flex-shrink: 0; padding: 8px; }

  /* Help "?" button + its portaled explainer popover (e.g. next to Route). */
  .anim-help-wrap { position: relative; display: inline-flex; }
  .anim-btn.anim-help-btn { padding: 6px; min-width: 0; color: var(--text-dim); }
  .anim-btn.anim-help-btn:hover { color: #1e6fbf; background: transparent; border-color: transparent; }
  .anim-btn.anim-help-btn svg { width: 16px; height: 16px; }
  .anim-help-pop {
    width: 300px;
    max-width: 88vw;
    padding: 12px 14px;
    background: #fff;
    border: 1px solid var(--border);
    border-radius: 10px;
    box-shadow: 0 12px 34px rgba(0, 0, 0, 0.18);
    color: var(--text);
    font-size: 13px;
    line-height: 1.5;
  }
  .anim-help-pop--portal { position: fixed; z-index: 1001; max-height: calc(100vh - 16px); overflow-y: auto; }
  .anim-help-pop[hidden] { display: none; }
  .anim-help-pop h4 { margin: 0 0 8px; font-size: 13.5px; font-weight: 700; color: var(--text); }
  .anim-help-pop ol { margin: 0 0 8px; padding-left: 20px; }
  .anim-help-pop ol li { margin: 0 0 5px; }
  .anim-help-pop ol li::marker { color: #1e6fbf; font-weight: 700; }
  .anim-help-pop .anim-help-tip {
    margin: 0; padding-top: 8px; border-top: 1px solid var(--border-soft);
    color: var(--text-dim); font-size: 12px;
  }

  /* On iPad widths reuse the same compaction the line-picker got — keep
     buttons but drop the verbose labels so the toolbar fits a single row. */
  @media (max-width: 1024px) {
    .anim-btn-label { display: none; }
  }

  .meta-fields { margin-top: 14px; display: flex; flex-direction: column; gap: 8px; flex-shrink: 0; }
  .meta-fields.meta-row {
    margin-top: 6px;
    flex-direction: row;
    gap: 6px;
  }
  .meta-fields.meta-row input { flex: 1; margin-bottom: 0; padding: 6px 10px; font-size: 13px; }
  .meta-fields.meta-row input#select-age { flex: 0 0 110px; }
  .meta-fields.meta-row .tags-input { flex: 1; min-width: 0; }

  /* ---------- Tag chip input ---------- */
  .tags-input {
    position: relative;
    display: flex; flex-wrap: wrap; align-items: center; gap: 4px;
    border: 1px solid var(--border);
    border-radius: 4px;
    background: #fff;
    padding: 4px 6px;
    min-height: 34px;
  }
  .tags-input:focus-within { border-color: var(--blue); }
  .tag-chips { display: contents; }
  .tag-chip {
    display: inline-flex; align-items: center; gap: 4px;
    background: #eef3ff;
    color: #1e3a8a;
    border: 1px solid #b8c8ee;
    border-radius: 12px;
    padding: 2px 4px 2px 8px;
    font-size: 12px;
    line-height: 1.4;
    white-space: nowrap;
  }
  .tag-chip .tag-remove {
    background: transparent; border: 0;
    color: #1e3a8a;
    padding: 0 4px;
    font-size: 14px;
    line-height: 1;
    cursor: pointer;
    border-radius: 50%;
  }
  .tag-chip .tag-remove:hover { background: rgba(30, 58, 138, .15); }
  #tag-entry {
    flex: 1; min-width: 80px;
    border: 0; outline: none;
    padding: 4px 4px;
    font-size: 13px;
    background: transparent;
  }
  .tag-autocomplete {
    position: absolute;
    top: calc(100% + 4px); left: 0; right: 0;
    background: #fff;
    border: 1px solid var(--border);
    border-radius: 4px;
    box-shadow: 0 6px 20px rgba(0,0,0,.08);
    z-index: 60;
    max-height: 200px;
    overflow-y: auto;
    padding: 4px;
  }
  .tag-autocomplete button {
    display: block; width: 100%;
    text-align: left;
    background: transparent;
    border: 0;
    padding: 6px 10px;
    border-radius: 3px;
    font-size: 13px;
    cursor: pointer;
    color: var(--text);
  }
  .tag-autocomplete button:hover,
  .tag-autocomplete button.active { background: var(--bg-soft); }

  /* ---------- Notes editor ---------- */
  .notes-editor {
    position: relative;
    border: 1px solid var(--border);
    border-radius: 4px;
    background: #fff;
    /* Important: do NOT clip — the icon picker popover lives inside this box. */
    overflow: visible;
  }
  .notes-editor:focus-within { border-color: var(--blue); }
  .notes-toolbar {
    display: flex; align-items: center; gap: 2px;
    padding: 4px;
    border-bottom: 1px solid var(--border-soft);
    background: var(--bg-soft);
  }
  .notes-toolbar button {
    background: transparent;
    border: 0;
    padding: 4px 8px;
    border-radius: 3px;
    font-size: 13px;
    color: var(--text);
    cursor: pointer;
  }
  .notes-toolbar button:hover { background: rgba(0,0,0,.06); }
  .notes-toolbar { position: relative; }
  .notes-toolbar-spacer { flex: 1; }
  /* Picker grid is positioned against the toolbar (full editor width) rather
     than the small button, so it never overflows the editor on narrow viewports. */
  .notes-icon-picker { position: static; }
  .icon-grid {
    position: absolute;
    /* Open ABOVE the toolbar so the popover never covers the text area. */
    bottom: calc(100% + 4px); top: auto;
    left: 0;
    display: grid;
    grid-template-columns: repeat(6, 38px);
    gap: 6px;
    padding: 8px;
    background: #fff;
    border: 1px solid var(--border);
    border-radius: 6px;
    box-shadow: 0 -6px 20px rgba(0,0,0,.12);
    z-index: 60;
    max-height: 240px;
    overflow-y: auto;
  }
  @media (max-width: 540px) {
    .icon-grid { grid-template-columns: repeat(5, 38px); }
  }
  /* `.icon-grid { display: grid }` ties with the user-agent `[hidden] { display: none }`
     rule on specificity, so this explicit override is needed to make the [hidden]
     attribute actually hide the popover. */
  .icon-grid[hidden] { display: none; }
  .icon-grid button {
    background: #fff;
    border: 1px solid var(--border-soft);
    border-radius: 4px;
    padding: 6px;
    cursor: pointer;
    display: flex; align-items: center; justify-content: center;
  }
  .icon-grid button:hover { background: var(--bg-soft); }
  .icon-grid img { width: 26px; height: 26px; object-fit: contain; }
  .notes-area {
    min-height: 70px;
    max-height: 200px;
    overflow-y: auto;
    padding: 8px 10px;
    font-size: 13px;
    line-height: 1.45;
    color: var(--text);
    outline: none;
  }
  .notes-area:empty::before {
    content: attr(data-placeholder);
    color: var(--text-dim);
    pointer-events: none;
  }
  .notes-area img.inline-icon {
    height: 1.5em; width: auto;
    vertical-align: -4px;
    margin: 0 2px;
  }
  /* List styles inside the notes editor — execCommand inserts native ul/ol
     elements; browser defaults often strip padding, so reset them here so
     bullets and numbers are actually visible. */
  .notes-area ul,
  .notes-area ol {
    margin: 4px 0 6px;
    padding-left: 22px;
  }
  .notes-area ul { list-style: disc outside; }
  .notes-area ol { list-style: decimal outside; }
  .notes-area li { margin: 1px 0; }
  .notes-area li::marker { color: var(--text-dim); }
  /* Skinny vertical divider between toolbar button groups. */
  .notes-toolbar-divider {
    width: 1px;
    align-self: stretch;
    background: var(--border-soft, #e6e8eb);
    margin: 4px 2px;
  }
  .meta-fields input {
    width: 100%;
    border: 1px solid var(--border);
    padding: 9px 12px;
    border-radius: 4px;
    font-family: inherit;
    font-size: 14px;
    color: var(--text);
    background: #fff;
    outline: none;
  }
  .meta-fields input:focus { border-color: var(--blue); }
  .meta-fields textarea {
    width: 100%;
    border: 1px solid var(--border);
    padding: 9px 12px;
    border-radius: 4px;
    font-family: inherit;
    font-size: 13px;
    color: var(--text);
    background: #fff;
    outline: none;
    resize: vertical;
    min-height: 50px;
  }
  .meta-fields textarea:focus { border-color: var(--blue); }

  /* RIGHT SIDEBAR */
  .sidebar {
    background: var(--bg);
    border-left: 1px solid var(--border-soft);
    display: flex;
    flex-direction: column;
    overflow: hidden;
  }
  .sidebar-tabs {
    display: flex;
    background: var(--panel-dark);
    border-bottom: 1px solid #1a1d22;
  }
  .sidebar-tab {
    flex: 1;
    text-align: center;
    padding: 12px 8px;
    cursor: pointer;
    font-weight: 700;
    font-size: 12px;
    letter-spacing: 1px;
    color: rgba(255,255,255,.65);
    border-bottom: 3px solid transparent;
    transition: all .15s;
  }
  .sidebar-tab.active {
    color: white;
    border-bottom-color: var(--brand-primary);
    background: var(--panel-accent);
  }
  .sidebar-tab:hover:not(.active) { color: white; }
  .sidebar-panel {
    display: none;
    flex: 1;
    flex-direction: column;
    overflow: hidden;
  }
  .sidebar-panel.active { display: flex; }
  .search-row { padding: 8px 12px; border-bottom: 1px solid var(--border-soft); }
  .search-row input {
    width: 100%;
    border: 1px solid var(--border);
    padding: 7px 12px;
    border-radius: 3px;
    font-family: inherit;
    font-size: 13px;
    text-transform: uppercase;
    letter-spacing: 0.5px;
    color: var(--text);
    background: #fff;
    outline: none;
  }
  /* Scope tabs (Personal | Team) at the top of the drill panel. */
  .drill-scope-tabs {
    display: flex;
    gap: 4px;
    padding: 6px 8px 0;
  }
  .drill-scope-tab {
    flex: 1;
    background: transparent;
    border: 1px solid transparent;
    border-bottom: 2px solid transparent;
    color: var(--text-dim);
    padding: 6px 8px;
    font-size: 12px;
    font-weight: 600;
    letter-spacing: 0.5px;
    text-transform: uppercase;
    cursor: pointer;
    border-radius: 4px 4px 0 0;
  }
  .drill-scope-tab:hover { color: var(--text); }
  .drill-scope-tab.active {
    color: var(--brand-primary);
    border-bottom-color: var(--brand-primary);
  }

  .drill-list {
    flex: 1;
    overflow-y: auto;
    padding: 4px;
  }
  .drill-folder-group { margin-bottom: 8px; }
  /* Folder header — now larger than the drill titles below it so the
     section hierarchy reads correctly (was 11px uppercase, which sat
     visually BELOW the 14px drill names). 2026-05-24 bump.
     The 2026-05-24 refinement adds:
       - More vertical padding (was 10/6, now 14/12) for breathing room.
       - A hairline bottom border so folders read as separate sections.
       - Dark-nav background when the folder is open, mirroring the
         top nav's --panel-dark — keeps the visual link between the
         "drawer" and the "main nav" while clearly marking which folder
         is currently expanded.
     `border-radius` clips the corners; padding-x stays tight so the
     drill cards underneath line up with the header text. */
  .drill-folder-head {
    display: flex; align-items: center; gap: 8px;
    padding: 14px 10px;
    color: var(--text);
    font-size: 16px;
    font-weight: 700;
    letter-spacing: 0;
    user-select: none;
    cursor: pointer;
    border-bottom: 1px solid var(--border-soft);
    border-radius: 6px;
    transition: background .15s, color .15s, border-color .15s, border-radius .15s;
  }
  /* Collapsed hover — subtle grey so the header feels clickable. */
  .drill-folder-group.collapsed > .drill-folder-head:hover {
    background: var(--bg-soft);
  }
  /* OPEN state — match the top nav's dark background. Inherited
     currentColor flips the chev + icon to white. The bottom border
     softens to a subtle inner-shadow line on dark so it still reads.
     Bottom corners squared off so the head visually "connects" into
     the folder body below. */
  .drill-folder-group:not(.collapsed) > .drill-folder-head {
    background: var(--panel-dark);
    color: #fff;
    border-bottom-color: rgba(255, 255, 255, 0.12);
    border-radius: 6px 6px 0 0;
  }
  .drill-folder-group:not(.collapsed) > .drill-folder-head:hover {
    /* Slight lift on hover even when open, so the open state still
       responds to interaction without losing its identity. */
    background: color-mix(in srgb, var(--panel-dark) 88%, #ffffff);
  }
  .drill-folder-head .chev {
    transition: transform .15s;
    display: inline-flex;
  }
  .drill-folder-group.collapsed .chev { transform: rotate(-90deg); }
  .drill-folder-group.collapsed .drill-folder-body { display: none; }
  /* Open folder body sits flush with the dark header above. A subtle
     side border ties it visually to the head's full-width band. */
  .drill-folder-group:not(.collapsed) > .drill-folder-body {
    padding: 8px 0 12px;
  }
  /* Drill-count badge — small pill on the right of the folder head.
     Adapts background tint to the head state (light on collapsed,
     translucent-white on open dark bg). Stays inside the same row via
     margin-left:auto. */
  .drill-folder-count {
    margin-left: auto;
    flex-shrink: 0;
    background: var(--bg-soft);
    color: var(--text-dim);
    font-size: 11px;
    font-weight: 600;
    line-height: 1;
    padding: 3px 8px;
    border-radius: 999px;
    letter-spacing: 0.2px;
  }
  .drill-folder-group:not(.collapsed) > .drill-folder-head .drill-folder-count {
    background: rgba(255, 255, 255, 0.14);
    color: rgba(255, 255, 255, 0.92);
  }
  /* Recent virtual folder — distinct accent when collapsed (brand red on
     light bg). When opened it adopts the same dark-nav treatment as
     normal folders for consistency, so the only difference visible is
     the clock icon inside the head. */
  .drill-folder-recent.collapsed .drill-folder-head { color: var(--brand-primary, var(--red)); }
  .drill-folder-recent-icon { flex-shrink: 0; }

  /* Scope radio toggle in the save modal */
  .scope-toggle {
    display: flex; gap: 16px;
    margin-bottom: 10px;
  }
  .scope-toggle label {
    display: inline-flex; align-items: center; gap: 6px;
    cursor: pointer;
    font-size: 13px;
    color: var(--text);
    font-weight: 400;
  }
  /* 2026-05-24 redesign: drill cards stack vertically — title on top,
     large full-width thumbnail, then meta (duration + tags), then a
     compact action row. The previous horizontal layout had a 72×40
     thumbnail that was too small to actually read the diagram. */
  .drill-card {
    display: flex;
    flex-direction: column;
    gap: 6px;
    padding: 10px;
    border: 1px solid var(--border-soft);
    border-radius: 6px;
    margin-bottom: 8px;
    cursor: pointer;
    transition: all .12s;
    background: white;
  }
  .drill-card:hover { background: var(--bg-soft); border-color: var(--border); }
  /* Active = drill is currently loaded in the canvas. Was a faint
     border + 8% tint; that didn't read on a sidebar with 20 cards.
     Now: stronger 14% tint, 2px border, and a 3px left accent bar
     in brand-secondary that runs the full card height so you can
     spot it from anywhere on screen. */
  .drill-card.active {
    border-color: var(--brand-secondary);
    background: color-mix(in srgb, var(--brand-secondary) 14%, #ffffff);
    position: relative;
    overflow: hidden;
  }
  .drill-card.active::before {
    content: '';
    position: absolute;
    left: 0; top: 0; bottom: 0;
    width: 3px;
    background: var(--brand-secondary);
  }
  /* Thumb wrap holds the img + an optional "Animated" badge overlay.
   * Full width of the card now (was 72×40); aspect-ratio keeps it
   * proportional regardless of card width. */
  .drill-card .thumb-wrap {
    position: relative;
    width: 100%;
    aspect-ratio: 16 / 9;
    flex-shrink: 0;
  }
  .drill-card .thumb {
    width: 100%;
    height: 100%;
    background: #fff;
    border: 1px solid var(--border-soft);
    border-radius: 4px;
    /* contain (not cover) so the entire rink + shapes are visible — at
       72×40 cover-cropping was fine, but with a full-width thumbnail
       cropping the rink edges off looks broken. */
    object-fit: contain;
    display: block;
  }
  /* "Animated drill" indicator — small ice-blue pill in the thumb's
   * top-right showing a play icon + frame count. Identifies multi-frame
   * drills at a glance from the drawer list. */
  .anim-badge {
    position: absolute;
    top: 3px;
    right: 3px;
    display: inline-flex;
    align-items: center;
    gap: 3px;
    padding: 2px 5px 2px 4px;
    background: rgba(30, 111, 191, 0.95);
    color: #fff;
    border-radius: 8px;
    font-family: inherit;
    font-size: 9px;
    font-weight: 700;
    line-height: 1;
    pointer-events: none;
    box-shadow: 0 1px 2px rgba(0, 0, 0, 0.25);
  }
  .anim-badge svg { width: 8px; height: 8px; }
  /* Loading state — when the drill's thumb hasn't been fetched yet
     (folder collapsed or fetch in flight). Flat light-grey background
     plus a spinning Coachly-puck logo via the .thumb-wrap pseudo
     element. Replaced with the real thumb the moment loadFolderThumbs
     swaps img.src and removes the loading class. */
  .drill-card .thumb--loading {
    background: #f4f5f7;
  }
  /* `:has(.thumb--loading)` triggers the spinner only while the img
     still carries the loading flag — same lifecycle as the old
     diagonal-stripes background. Modern Safari/Chrome (and the iPad
     PWA) all support :has(); older browsers degrade to the flat grey
     above. Pointer-events: none so the spinner can't intercept the
     card's drag/tap.

     The spinner itself: a 3/4 red ring (270° arc, stroke only, no fill)
     drawn as inline SVG. The CSS animation rotates the whole image so
     the open quadrant chases around the circle — classic loading-ring
     look. No puck silhouette anymore. */
  .drill-card .thumb-wrap:has(.thumb--loading)::before {
    content: '';
    position: absolute;
    inset: 0;
    background:
      center / 20px 20px no-repeat
      url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><circle cx='12' cy='12' r='9' fill='none' stroke='%23e7e9ec' stroke-width='2.5'/><path d='M12 3 a 9 9 0 0 1 9 9' fill='none' stroke='%23d4302b' stroke-width='2.5' stroke-linecap='round'/></svg>");
    animation: drill-thumb-spin 0.8s linear infinite;
    pointer-events: none;
    z-index: 1;
  }
  @keyframes drill-thumb-spin {
    to { transform: rotate(360deg); }
  }

  /* Drill drawer boot placeholder. The drawer's #drill-list starts
     empty in the markup, with a span of dead air between page-load and
     pc:ready (when api.me() resolves and renderDrills() finally paints).
     This spinner fills that gap so the coach gets immediate feedback
     instead of an empty rail. The whole element gets replaced by
     renderDrills() — no JS hide-on-ready needed. */
  .drill-list-loading {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 12px;
    padding: 48px 16px;
    color: var(--text-dim);
    font-size: 12.5px;
  }
  .drill-list-loading-spinner {
    width: 28px;
    height: 28px;
    background:
      center / 28px 28px no-repeat
      url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><circle cx='12' cy='12' r='9' fill='none' stroke='%23e7e9ec' stroke-width='2.5'/><path d='M12 3 a 9 9 0 0 1 9 9' fill='none' stroke='%23d4302b' stroke-width='2.5' stroke-linecap='round'/></svg>");
    animation: drill-thumb-spin 0.8s linear infinite;
  }
  .drill-list-loading-label {
    text-transform: uppercase;
    letter-spacing: 0.6px;
    font-weight: 600;
  }
  /* `.info` is no longer in the markup after the 2026-05-24 vertical
     redesign — title + meta sit as direct children of `.drill-card`.
     Keeping the legacy selector is harmless if any old cached HTML
     somewhere still wraps them. */
  .drill-card .info { min-width: 0; }
  .drill-card .nm {
    font-size: 14px;
    font-weight: 600;
    color: var(--text);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    line-height: 1.3;
  }
  /* Meta row: minutes badge + tag chips, single line. Tags wrap into
     `.dc-tags` which can overflow with an ellipsis on tight widths. */
  .drill-card .meta {
    font-size: 11px;
    color: var(--text-dim);
    display: flex;
    align-items: center;
    gap: 6px;
    min-width: 0;
  }
  .drill-card .dc-mins {
    flex-shrink: 0;
    background: var(--bg-soft);
    padding: 2px 7px;
    border-radius: 10px;
    font-weight: 600;
    color: var(--text);
    font-size: 11px;
  }
  .drill-card .dc-tags {
    display: flex;
    gap: 4px;
    overflow: hidden;
    min-width: 0;
  }
  .drill-card .dc-tag {
    flex-shrink: 0;
    background: color-mix(in srgb, var(--brand-secondary) 12%, #ffffff);
    color: color-mix(in srgb, var(--brand-secondary) 80%, #000000);
    padding: 2px 7px;
    border-radius: 10px;
    font-size: 11px;
    font-weight: 500;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    max-width: 100px;
  }
  .drill-card .dc-tag--more {
    background: var(--bg-soft);
    color: var(--text-dim);
    max-width: none;
  }
  /* Acts row is now horizontal, anchored to the right edge of the card. */
  .drill-card .acts {
    display: flex;
    flex-direction: row;
    justify-content: flex-end;
    gap: 4px;
    flex-shrink: 0;
    margin-top: 2px;
  }
  /* Favourite star — top-right of the card, separate from the action
     row so it remains glanceable. Off-state is hollow grey; on-state is
     a filled red star with a slight glow. (2026-05-26) */
  .drill-card .fav {
    position: absolute;
    top: 8px;
    right: 8px;
    z-index: 2;
    background: rgba(255, 255, 255, 0.88);
    backdrop-filter: blur(2px);
    border: none;
    border-radius: 999px;
    width: 26px;
    height: 26px;
    padding: 0;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    color: var(--text-dim);
    cursor: pointer;
    transition: color .15s, transform .15s, background .15s;
  }
  .drill-card .fav:hover { color: var(--red); transform: scale(1.08); }
  .drill-card .fav.fav--on {
    color: var(--red, #7c5cff);
    background: rgba(255, 255, 255, 0.96);
  }
  /* The active card has its own ::before accent bar — we already use that
     to mark the open drill. The fav button sits ON the thumbnail's
     top-right corner; need position:relative on the card for it to
     anchor correctly. */
  .drill-card { position: relative; }

  /* Footer meta row — "Used in N plans" + "edited X ago". Sits below the
     main meta line as a smaller, dimmer accessory row so the primary tag
     chips stay prominent. Hidden entirely when both badges are empty. */
  .drill-card .dc-foot-row {
    display: flex;
    gap: 8px;
    align-items: center;
    font-size: 10.5px;
    color: var(--text-dim);
    margin-top: -2px;
  }
  .drill-card .dc-foot {
    display: inline-flex;
    align-items: center;
    line-height: 1;
    white-space: nowrap;
  }
  .drill-card .dc-foot--plans {
    color: color-mix(in srgb, var(--brand-secondary) 80%, #000000);
    font-weight: 600;
  }
  .drill-card .dc-foot--time {
    color: var(--text-dim);
  }

  /* Sort popover — replaces the old native <select>. Sits inline with
     the search input. Trigger button is a small pill with the current
     mode's short label; tapping it opens an anchored popover menu.
     2026-05-26. */
  .search-row { display: flex; align-items: center; gap: 6px; }
  .search-row input { flex: 1; min-width: 0; }
  .drill-sort-wrap {
    position: relative;
    flex-shrink: 0;
  }
  .drill-sort-trigger {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    padding: 6px 10px;
    border: 1px solid var(--border-soft);
    border-radius: 6px;
    background: white;
    color: var(--text);
    font-size: 11px;
    font-weight: 600;
    cursor: pointer;
    line-height: 1;
    transition: background .12s, border-color .12s;
  }
  .drill-sort-trigger:hover { background: var(--bg-soft); border-color: var(--border); }
  .drill-sort-trigger[aria-expanded="true"] {
    background: var(--bg-soft);
    border-color: var(--border);
  }
  .drill-sort-trigger svg { flex-shrink: 0; color: var(--text-dim); }
  .drill-sort-trigger-label { letter-spacing: 0.2px; }
  /* Popover menu anchored under the trigger. Floats above the drill
     list — z-index above the folder headers (which sit at default 0). */
  .drill-sort-menu {
    position: absolute;
    top: calc(100% + 4px);
    right: 0;
    min-width: 180px;
    background: white;
    border: 1px solid var(--border);
    border-radius: 6px;
    box-shadow: 0 8px 24px rgba(0, 0, 0, 0.12);
    padding: 4px;
    z-index: 50;
  }
  .drill-sort-option {
    display: flex;
    align-items: center;
    gap: 8px;
    width: 100%;
    padding: 8px 10px;
    border: none;
    background: transparent;
    text-align: left;
    font-size: 13px;
    color: var(--text);
    border-radius: 4px;
    cursor: pointer;
  }
  .drill-sort-option:hover { background: var(--bg-soft); }
  .drill-sort-option.is-active {
    background: color-mix(in srgb, var(--brand-secondary) 10%, #ffffff);
    color: color-mix(in srgb, var(--brand-secondary) 80%, #000000);
    font-weight: 600;
  }
  /* Checkmark via ::before on the active option keeps the layout stable
     between active/inactive states (each row stays the same width). */
  .drill-sort-option::before {
    content: '';
    width: 14px;
    height: 14px;
    flex-shrink: 0;
    display: inline-block;
    background-position: center;
    background-repeat: no-repeat;
    background-size: 14px 14px;
  }
  .drill-sort-option.is-active::before {
    background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%231e6fbf' stroke-width='3' stroke-linecap='round' stroke-linejoin='round'><polyline points='20 6 9 17 4 12'/></svg>");
  }

  /* Empty-folder state inside an open folder body. */
  .drill-folder-empty {
    padding: 12px 14px;
    color: var(--text-dim);
    font-size: 12px;
    font-style: italic;
    text-align: center;
  }
  /* Favourites variant — slightly taller with the star icon stacked above
     a two-line hint so the empty state reads as intentional, not broken. */
  .drill-folder-empty--fav {
    padding: 18px 14px;
    font-style: normal;
    line-height: 1.5;
  }
  .drill-folder-empty--fav svg { color: var(--text-dim); }
  .drill-folder-empty-hint {
    font-size: 11px;
    color: var(--text-dim);
    opacity: 0.85;
    margin-top: 2px;
  }

  /* Favourites virtual folder — gold-tinted icon when collapsed, same
     dark-nav treatment as other folders when open. */
  .drill-folder-favorites.collapsed .drill-folder-head {
    color: #b8860b; /* dark goldenrod */
  }
  .drill-folder-favorites .drill-folder-favorites-icon { flex-shrink: 0; }
  .drill-card .acts button {
    background: transparent;
    border: none;
    cursor: pointer;
    padding: 3px;
    color: var(--text-dim);
    border-radius: 3px;
  }
  .drill-card .acts button:hover { color: var(--text); background: var(--bg-soft); }
  .drill-card .acts .del:hover { color: var(--red); }
  .empty-state {
    padding: 30px 16px;
    text-align: center;
    color: var(--text-dim);
    font-size: 13px;
  }
  .empty-state .icon { font-size: 36px; margin-bottom: 6px; opacity: .3; }

  /* Plans panel */
  .plan-toolbar {
    display: flex;
    gap: 6px;
    padding: 8px 12px;
    border-bottom: 1px solid var(--border-soft);
  }
  .plan-btn {
    flex: 1;
    background: var(--brand-secondary);
    color: white;
    border: none;
    padding: 8px 12px;
    border-radius: 4px;
    font-family: inherit;
    font-size: 13px;
    cursor: pointer;
    font-weight: 500;
    transition: filter .15s;
  }
  .plan-btn:hover, .plan-btn:focus { filter: brightness(0.9); }
  .plan-btn.secondary {
    background: white;
    color: var(--text);
    border: 1px solid var(--border);
  }
  .plan-btn.secondary:hover { background: var(--bg-soft); }
  .plan-list {
    flex: 1;
    overflow-y: auto;
    padding: 4px;
  }
  /* Practice Plans grid (2026-05-26 polish — matches dashboard widget
     idiom). #plan-grid is rendered by page_plans.js as a flat list of
     .plan-card items; we lay them out as a responsive CSS grid so they
     sit side-by-side on desktop instead of stacking. The earlier
     stacked-stack layout made the page look like a long form. */
  #plan-grid {
    display: grid;
    grid-template-columns: 1fr;
    gap: 16px;
  }
  @media (min-width: 720px) {
    #plan-grid { grid-template-columns: repeat(2, 1fr); }
  }
  @media (min-width: 1080px) {
    #plan-grid { grid-template-columns: repeat(3, 1fr); }
  }

  .plan-card {
    border: 1px solid var(--border-soft);
    border-radius: 14px;
    margin-bottom: 0;
    background: white;
    overflow: hidden;
    transition: box-shadow .15s, transform .15s, border-color .15s;
    position: relative;
    display: flex;
    flex-direction: column;
  }
  .plan-card:hover {
    box-shadow: 0 12px 28px -12px rgba(0, 0, 0, 0.14);
    transform: translateY(-2px);
  }
  /* Top accent ribbon — green when attached to an upcoming practice
     (active), brand-secondary otherwise. Mirrors the colour treatment
     used on dashboard widgets so the visual language is shared. */
  .plan-card::before {
    content: '';
    position: absolute;
    top: 0; left: 0; right: 0;
    height: 3px;
    background: var(--brand-secondary, #1e6fbf);
  }
  .plan-card.has-upcoming::before { background: var(--green, #1f9e5a); }
  .plan-card.is-visible-to-players::before { background: var(--brand-secondary, #1e6fbf); }

  .plan-card .head {
    display: flex;
    align-items: flex-start;
    padding: 16px 18px 12px;
    cursor: pointer;
    justify-content: space-between;
    gap: 10px;
    transition: background .12s;
  }
  .plan-card .head:hover { background: var(--bg-soft); }
  .plan-card.expanded .head { background: var(--bg-soft); border-bottom: 1px solid var(--border-soft); }
  /* The grid card variant doesn't use .card-head + .name/.summary —
     page_plans.js renders <h2> directly inside .plan-card-head-info. */
  .plan-card .plan-card-head-info { flex: 1; min-width: 0; }
  .plan-card h2 {
    margin: 0 0 4px;
    font-size: 16px;
    font-weight: 700;
    color: var(--text);
    letter-spacing: -0.01em;
    line-height: 1.25;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
  }
  .plan-card .sub {
    font-size: 12px;
    color: var(--text-dim);
    line-height: 1.4;
  }
  .plan-card .plan-card-head-actions { display: flex; gap: 4px; flex-shrink: 0; }
  .plan-card .btn-icon {
    background: transparent;
    border: none;
    cursor: pointer;
    padding: 6px;
    color: var(--text-dim);
    border-radius: 6px;
    transition: color .12s, background .12s;
  }
  .plan-card .btn-icon:hover { color: var(--text); background: var(--bg-soft); }
  .plan-card .btn-icon.del:hover { color: var(--red); background: color-mix(in srgb, var(--red) 10%, white); }
  /* Legacy .acts wrapper (some flows still emit it) */
  .plan-card .head .acts { display: flex; gap: 4px; }
  .plan-card .head .acts button {
    background: transparent;
    border: none;
    cursor: pointer;
    padding: 6px;
    color: var(--text-dim);
    border-radius: 6px;
  }
  .plan-card .head .acts button:hover { color: var(--text); background: var(--bg-soft); }
  .plan-card .head .acts .del:hover { color: var(--red); }
  /* Body — drill list + Run Practice action. Visible by default on the
     grid view (no longer click-to-expand); cards are short enough now
     that everything fits. */
  .plan-card .plan-body {
    padding: 0 18px 14px;
    display: flex;
    flex-direction: column;
    gap: 5px;
  }
  /* Legacy .body class kept for any older render paths */
  .plan-card .body { display: none; padding: 8px 12px; background: #fafafa; }
  .plan-card.expanded .body { display: block; }
  .plan-drill {
    display: flex;
    gap: 10px;
    padding: 7px 10px;
    background: var(--bg-soft);
    border: 1px solid var(--border-soft);
    border-radius: 8px;
    margin-bottom: 0;
    cursor: pointer;
    align-items: center;
    transition: background .12s, border-color .12s;
  }
  .plan-drill:hover {
    background: white;
    border-color: var(--border);
  }
  .plan-drill .idx {
    width: 22px; height: 22px;
    background: var(--brand-secondary, #1e6fbf);
    color: white;
    border-radius: 50%;
    font-size: 11px;
    font-weight: 700;
    display: grid;
    place-items: center;
    flex-shrink: 0;
    font-family: inherit;
  }
  .plan-drill .nm {
    flex: 1;
    font-size: 13px;
    font-weight: 500;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
  }
  .plan-drill .mins {
    font-size: 11px;
    color: var(--text-dim);
    background: white;
    padding: 2px 8px;
    border-radius: 999px;
    font-weight: 600;
    flex-shrink: 0;
  }
  .plan-drill-overflow {
    padding: 4px 10px;
    font-size: 11px;
    color: var(--text-dim);
    font-style: italic;
  }
  .plan-actions {
    margin-top: 8px;
    display: flex;
    gap: 6px;
  }
  .plan-actions .run {
    flex: 1;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 6px;
    padding: 9px 14px;
    border-radius: 8px;
    font-weight: 600;
    font-size: 13px;
  }
  /* Small chips inside the plan card head (upcoming / private / visible). */
  .plan-upcoming-chip,
  .plan-private-badge,
  .plan-visible-badge {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    margin-top: 6px;
    padding: 2px 8px;
    border-radius: 999px;
    font-size: 11px;
    font-weight: 600;
  }
  .plan-upcoming-chip {
    background: color-mix(in srgb, var(--green, #1f9e5a) 12%, white);
    color: color-mix(in srgb, var(--green, #1f9e5a) 75%, #000);
  }
  .plan-private-badge {
    background: var(--bg-soft);
    color: var(--text-dim);
  }
  .plan-visible-badge {
    background: color-mix(in srgb, var(--brand-secondary, #1e6fbf) 14%, white);
    color: color-mix(in srgb, var(--brand-secondary, #1e6fbf) 80%, #000);
  }
  .plan-drill .rm {
    background: transparent;
    border: none;
    cursor: pointer;
    color: var(--text-dim);
    padding: 2px;
  }
  .plan-drill .rm:hover { color: var(--red); }
  .plan-drill .rate {
    background: transparent;
    border: none;
    cursor: pointer;
    color: #ffb43a;
    padding: 2px;
    margin-right: 2px;
  }
  .plan-drill .rate:hover { opacity: 0.7; }
  .plan-actions {
    display: flex;
    gap: 6px;
    margin-top: 8px;
  }
  .plan-actions button {
    flex: 1;
    background: white;
    color: var(--text);
    border: 1px solid var(--border);
    padding: 6px 10px;
    border-radius: 3px;
    font-size: 12px;
    cursor: pointer;
  }
  .plan-actions button:hover { background: var(--bg-soft); }
  .plan-actions button.primary {
    background: var(--green);
    color: white;
    border-color: var(--green);
  }
  .plan-actions button.primary:hover { background: #197a47; }

  /* Run Practice — full-screen modal, light theme with brand accents */
  .run-screen {
    position: fixed; inset: 0;
    background: var(--bg-soft, #f4f5f7);
    display: none;
    flex-direction: column;
    z-index: 500;
    color: var(--text);
  }
  .run-screen.show { display: flex; }

  /* Top bar: exit | plan title + meta | progress dots | total elapsed */
  .run-topbar {
    display: grid;
    grid-template-columns: auto 1fr auto auto;
    gap: 20px;
    align-items: center;
    padding: 14px 24px;
    background: #fff;
    border-bottom: 1px solid var(--border-soft, #e6e8eb);
  }
  .run-exit {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    padding: 8px 12px 8px 10px;
    background: #fff;
    border: 1px solid var(--border, #d8dce1);
    border-radius: 8px;
    color: var(--text);
    cursor: pointer;
    font: inherit;
    font-size: 13px;
    font-weight: 600;
  }
  .run-exit:hover {
    background: color-mix(in srgb, var(--brand-primary, var(--red)) 8%, #fff);
    border-color: var(--brand-primary, var(--red));
    color: var(--brand-primary, var(--red));
  }
  .run-exit svg { width: 16px; height: 16px; }
  .run-topbar-meta { min-width: 0; }
  .run-plan-name {
    font-size: 17px;
    font-weight: 700;
    letter-spacing: 0.2px;
    color: var(--text);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
  }
  .run-plan-sub {
    font-size: 12px;
    color: var(--text-dim);
    margin-top: 1px;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
  }
  .run-progress {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    flex-wrap: nowrap;
    overflow-x: auto;
    scrollbar-width: none;
  }
  .run-progress::-webkit-scrollbar { display: none; }
  .run-progress-dot {
    min-width: 28px; height: 28px;
    padding: 0 8px;
    background: var(--bg-soft, #f4f5f7);
    border: 1px solid var(--border-soft, #e6e8eb);
    color: var(--text-dim);
    border-radius: var(--r-pill, 999px);
    font-size: 11.5px;
    font-weight: 700;
    cursor: pointer;
    font-variant-numeric: tabular-nums;
    transition: background var(--t-fast, 120ms) var(--ease, ease);
  }
  .run-progress-dot:hover { background: #fff; border-color: var(--border, #d8dce1); color: var(--text); }
  .run-progress-dot.is-done {
    background: color-mix(in srgb, var(--green, #1f9e5a) 12%, #fff);
    border-color: color-mix(in srgb, var(--green, #1f9e5a) 40%, transparent);
    color: var(--green, #1f9e5a);
  }
  .run-progress-dot.is-current {
    background: var(--brand-primary, var(--red));
    border-color: var(--brand-primary, var(--red));
    color: #fff;
    box-shadow: 0 0 0 3px color-mix(in srgb, var(--brand-primary, var(--red)) 22%, transparent);
  }
  .run-elapsed-box { text-align: right; }
  .run-elapsed {
    font-size: 18px;
    font-weight: 700;
    font-variant-numeric: tabular-nums;
    letter-spacing: -0.5px;
    line-height: 1;
    color: var(--text);
  }
  .run-elapsed-label {
    font-size: 10px;
    font-weight: 700;
    letter-spacing: 1px;
    text-transform: uppercase;
    color: var(--text-dim);
    margin-top: 3px;
  }

  /* Body: 2-col grid (drill detail | side panel). The grid needs an explicit
     1fr row so the cells fill the available flex height — without it, rows
     fall back to content size and .run-main collapses to a sliver. */
  .run-body {
    flex: 1;
    display: grid;
    grid-template-columns: minmax(0, 1fr) 360px;
    grid-template-rows: 1fr;
    min-height: 0;
    overflow: hidden;
  }
  /* Grid layout: drill header (content), rink (fills available vertical
     space), description (content-sized + capped + internal scroll).
     The rink ALWAYS fills the middle row so its visibility is guaranteed
     regardless of how tall the description gets or which surface the drill
     uses — half-ice, cross-ice, etc. each fit cleanly via object-fit. */
  .run-main {
    min-height: 0;
    overflow: hidden;
    padding: 20px 28px;
    display: grid;
    grid-template-rows: auto minmax(0, 1fr) auto;
    gap: 14px;
  }
  .run-drill-eyebrow {
    font-size: 11px;
    font-weight: 800;
    letter-spacing: 1.4px;
    text-transform: uppercase;
    color: var(--brand-primary, var(--red));
  }
  .run-drill-title {
    margin: 4px 0 0;
    font-size: 30px;
    font-weight: 800;
    letter-spacing: -0.3px;
    line-height: 1.15;
    color: var(--text);
  }
  .run-drill-meta {
    margin-top: 4px;
    font-size: 12.5px;
    color: var(--text-dim);
    letter-spacing: 0.3px;
  }
  .run-rink-wrap {
    position: relative;
    background: #fff;
    border: 1px solid var(--border-soft, #e6e8eb);
    border-radius: 10px;
    padding: 12px;
    display: flex;
    align-items: center;
    justify-content: center;
    /* min-height: 0 so the rink wrap shrinks into the grid cell instead of
       being driven by the image's intrinsic size. Combined with the explicit
       width/height: 100% on .run-rink below, object-fit: contain can do its
       job and every surface aspect (full / half / cross / zone / …) fits. */
    min-height: 0;
    overflow: hidden;
  }
  .run-rink {
    display: block;
    width: 100%;
    height: 100%;
    /* `object-fit: contain` only takes effect when both width and height are
       set (not auto) — that's the change vs. before, which caused half-ice
       thumbs to render at their intrinsic size and overflow. */
    object-fit: contain;
  }
  .run-rink-empty {
    color: var(--text-dim);
    font-size: 13px;
    font-style: italic;
  }
  /* Key Points panel — sits below the rink, scrolls its own body when the
     content overflows so the rink above stays visible. Header is a clickable
     toggle (collapsed on mobile by default). Capped at 35vh so the rink
     never gets crowded out, regardless of how much description text exists. */
  .run-desc-wrap {
    min-height: 0;
    max-height: 35vh;
    display: flex;
    flex-direction: column;
    background: #fff;
    border: 1px solid var(--border-soft, #e6e8eb);
    border-radius: 10px;
    overflow: hidden;
  }
  .run-desc-wrap.is-collapsed { max-height: none; }   /* toggle row only — no body to cap */
  .run-desc-toggle {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 8px;
    width: 100%;
    padding: 12px 16px;
    background: transparent;
    border: 0;
    cursor: pointer;
    font: inherit;
    font-size: 11px;
    font-weight: 800;
    letter-spacing: 1.2px;
    text-transform: uppercase;
    color: var(--text-dim);
    text-align: left;
    flex-shrink: 0;
  }
  .run-desc-toggle:hover { background: var(--bg-soft, #f4f5f7); color: var(--text); }
  .run-desc-chev {
    width: 14px; height: 14px;
    flex-shrink: 0;
    transition: transform var(--t-fast, 120ms) var(--ease, ease);
  }
  .run-desc-wrap.is-collapsed .run-desc-chev { transform: rotate(-90deg); }
  .run-desc-wrap.is-collapsed .run-desc { display: none; }
  .run-desc {
    flex: 1;
    min-height: 0;
    overflow-y: auto;
    padding: 0 18px 16px;
    font-size: 14.5px;
    line-height: 1.55;
    color: var(--text);
  }
  .run-desc p { margin: 0 0 8px; }
  .run-desc p:last-child { margin-bottom: 0; }
  .run-desc ul, .run-desc ol { margin: 6px 0 8px; padding-left: 22px; }
  .run-desc ul { list-style: disc outside; }
  .run-desc ol { list-style: decimal outside; }
  .run-desc li { margin: 2px 0; }
  .run-desc li::marker { color: var(--text-dim); }
  .run-desc img.inline-icon {
    height: 1.1em; width: auto; vertical-align: -2px; margin: 0 2px;
  }

  /* Side panel: timer + up next */
  .run-side {
    min-height: 0;
    overflow-y: auto;
    padding: 24px;
    background: #fff;
    border-left: 1px solid var(--border-soft, #e6e8eb);
    display: flex;
    flex-direction: column;
    gap: 22px;
  }
  .run-timer-card {
    background: var(--bg-soft, #f4f5f7);
    border: 1px solid var(--border-soft, #e6e8eb);
    border-radius: 14px;
    padding: 20px;
    text-align: center;
  }
  .run-timer-label {
    font-size: 11px;
    font-weight: 800;
    letter-spacing: 1.4px;
    text-transform: uppercase;
    color: var(--text-dim);
  }
  .run-timer-display {
    margin-top: 6px;
    font-size: 70px;
    font-weight: 800;
    font-variant-numeric: tabular-nums;
    letter-spacing: -3px;
    line-height: 1;
    color: var(--text);
  }
  .run-timer-display.warning { color: #d68a18; }
  .run-timer-display.expired { color: var(--red); animation: pulse 1s infinite; }
  @keyframes pulse {
    0%, 100% { opacity: 1; }
    50% { opacity: 0.55; }
  }
  .run-timer-bar {
    height: 6px;
    background: var(--border-soft, #e6e8eb);
    border-radius: var(--r-pill, 999px);
    margin: 14px 0 16px;
    overflow: hidden;
  }
  .run-timer-fill {
    height: 100%;
    width: 0%;
    background: linear-gradient(90deg, var(--brand-primary, var(--red)), color-mix(in srgb, var(--brand-primary, var(--red)) 65%, #ff8a4a));
    transition: width 1s linear;
  }
  .run-timer-controls {
    display: flex; gap: 8px; align-items: center; justify-content: center;
  }
  .run-timer-btn {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    padding: 10px 18px;
    border-radius: 8px;
    border: 0;
    cursor: pointer;
    font: inherit;
    font-size: 13.5px;
    font-weight: 700;
    transition: filter var(--t-fast, 120ms) var(--ease, ease), background var(--t-fast, 120ms) var(--ease, ease);
  }
  .run-timer-btn svg { width: 14px; height: 14px; }
  .run-timer-btn.primary {
    background: var(--brand-primary, var(--red));
    color: #fff;
  }
  .run-timer-btn.primary:hover:not(:disabled) { filter: brightness(0.92); }
  .run-timer-btn.primary:disabled { opacity: 0.5; cursor: not-allowed; }
  .run-timer-btn.ghost {
    background: #fff;
    color: var(--text);
    border: 1px solid var(--border, #d8dce1);
    padding: 10px 12px;
  }
  .run-timer-btn.ghost:hover { background: var(--bg-soft, #f4f5f7); border-color: var(--text-dim); }
  /* Swap icon visibility based on data-state. */
  .run-timer-btn .icon-pause { display: none; }
  .run-timer-btn[data-state="pause"] .icon-play { display: none; }
  .run-timer-btn[data-state="pause"] .icon-pause { display: inline; }

  /* Practice Mode v2 toggle row — Phase 8c 2026-06-14. Two pill toggles
     (Voice, Auto-next) under the main timer buttons. Active state lights
     up with the brand secondary color so the coach can tell at a glance
     which assists are armed. */
  .run-mode-toggles {
    display: flex;
    gap: 8px;
    margin-top: 10px;
  }
  .run-mode-toggle {
    flex: 1 1 0;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 6px;
    padding: 6px 10px;
    background: rgba(255, 255, 255, 0.06);
    border: 1px solid rgba(255, 255, 255, 0.18);
    border-radius: 999px;
    color: rgba(255, 255, 255, 0.7);
    font-size: 11px;
    font-weight: 600;
    letter-spacing: 0.3px;
    cursor: pointer;
    transition: background 120ms ease, color 120ms ease, border-color 120ms ease;
  }
  .run-mode-toggle:hover {
    background: rgba(255, 255, 255, 0.12);
    color: #fff;
  }
  .run-mode-toggle[data-on="1"] {
    background: color-mix(in srgb, var(--brand-secondary) 30%, transparent);
    border-color: color-mix(in srgb, var(--brand-secondary) 65%, transparent);
    color: #fff;
  }
  .run-mode-toggle .run-voice-waves { opacity: 0.4; }
  .run-mode-toggle[data-on="1"] .run-voice-waves { opacity: 1; }

  /* Practice Mode v2: energy zone color coding on the progress dots.
     Each drill row carries a data-zone attribute derived from its tags
     (warm-up, skill, scrimmage, cooldown). The current/done dots get a
     left-bar accent in the zone color so the coach sees the practice's
     intensity arc at a glance. */
  .run-progress-dot[data-zone="warmup"]   { box-shadow: inset 3px 0 0 #6dd3ff; }
  .run-progress-dot[data-zone="skill"]    { box-shadow: inset 3px 0 0 #5cdd9b; }
  .run-progress-dot[data-zone="battle"]   { box-shadow: inset 3px 0 0 #f3744c; }
  .run-progress-dot[data-zone="scrimmage"]{ box-shadow: inset 3px 0 0 #e74c3c; }
  .run-progress-dot[data-zone="cooldown"] { box-shadow: inset 3px 0 0 #b69dff; }

  /* Practice Mode v2: visual flash when a voice cue fires — gives
     hearing-impaired coaches the same warning. 1.2s sweep, no layout
     shift. */
  @keyframes run-cue-flash {
    0%   { box-shadow: 0 0 0 0 color-mix(in srgb, var(--brand-secondary) 70%, transparent); }
    50%  { box-shadow: 0 0 0 12px color-mix(in srgb, var(--brand-secondary) 0%, transparent); }
    100% { box-shadow: 0 0 0 0 transparent; }
  }
  .run-timer-display.is-cued { animation: run-cue-flash 1200ms ease-out; }

  .run-upnext-label {
    font-size: 11px;
    font-weight: 800;
    letter-spacing: 1.2px;
    text-transform: uppercase;
    color: var(--text-dim);
    margin-bottom: 8px;
  }
  .run-upnext-list { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 4px; }
  .run-upnext-item {
    display: grid;
    grid-template-columns: 26px minmax(0, 1fr);
    gap: 10px;
    align-items: center;
    padding: 8px 10px;
    background: var(--bg-soft, #f4f5f7);
    border: 1px solid var(--border-soft, #e6e8eb);
    border-radius: 8px;
    cursor: pointer;
    transition: background var(--t-fast, 120ms) var(--ease, ease), border-color var(--t-fast, 120ms) var(--ease, ease);
  }
  .run-upnext-item:hover {
    background: #fff;
    border-color: var(--brand-primary, var(--red));
  }
  .run-upnext-item.is-past { opacity: 0.5; }
  .run-upnext-num {
    width: 26px; height: 26px;
    display: grid; place-items: center;
    background: #fff;
    border: 1px solid var(--border-soft, #e6e8eb);
    border-radius: 50%;
    font-size: 11.5px;
    font-weight: 700;
    color: var(--text-dim);
  }
  .run-upnext-name {
    font-size: 13px;
    font-weight: 600;
    color: var(--text);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
  }
  .run-upnext-mins {
    font-size: 11px;
    color: var(--text-dim);
    margin-top: 2px;
  }

  /* Bottom footer with Previous / Next */
  .run-footer {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 10px;
    padding: 14px 24px;
    background: #fff;
    border-top: 1px solid var(--border-soft, #e6e8eb);
  }
  .run-nav-btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 8px;
    padding: 14px 18px;
    background: #fff;
    border: 1px solid var(--border, #d8dce1);
    border-radius: 10px;
    color: var(--text);
    font: inherit;
    font-size: 14px;
    font-weight: 700;
    cursor: pointer;
    transition: background var(--t-fast, 120ms) var(--ease, ease), border-color var(--t-fast, 120ms) var(--ease, ease);
  }
  .run-nav-btn svg { width: 18px; height: 18px; }
  .run-nav-btn:hover:not(:disabled) {
    background: color-mix(in srgb, var(--brand-primary, var(--red)) 6%, #fff);
    border-color: var(--brand-primary, var(--red));
    color: var(--brand-primary, var(--red));
  }
  .run-nav-btn:disabled { opacity: 0.4; cursor: not-allowed; }
  .run-nav-next {
    background: var(--brand-primary, var(--red));
    border-color: var(--brand-primary, var(--red));
    color: #fff;
  }
  .run-nav-next:hover:not(:disabled) {
    filter: brightness(0.92);
    background: var(--brand-primary, var(--red));
    border-color: var(--brand-primary, var(--red));
    color: #fff;
  }
  .run-nav-next.is-finish {
    background: var(--green, #1f9e5a);
    border-color: var(--green, #1f9e5a);
  }
  .run-nav-next.is-finish:hover { background: var(--green, #1f9e5a); border-color: var(--green, #1f9e5a); color: #fff; }

  @media (max-width: 980px) {
    .run-body { grid-template-columns: 1fr; }
    .run-side { border-left: 0; border-top: 1px solid var(--border-soft, #e6e8eb); }
  }
  @media (max-width: 720px) {
    .run-topbar { grid-template-columns: auto 1fr auto; padding: 10px 14px; gap: 10px; }
    .run-progress { display: none; } /* re-shown via Up Next list */
    .run-elapsed { font-size: 15px; }
    .run-main { padding: 14px 14px; gap: 10px; }
    .run-drill-title { font-size: 22px; }
    .run-side { padding: 14px; }
    .run-timer-display { font-size: 56px; letter-spacing: -2px; }
    .run-footer { padding: 10px 14px; }
    .run-nav-btn { padding: 12px 14px; font-size: 13px; }
  }

  /* Style FAB & popover */
  .fab {
    position: fixed;
    bottom: 22px;
    right: 320px;
    width: 44px;
    height: 44px;
    border-radius: 50%;
    background: var(--blue);
    color: white;
    display: grid;
    place-items: center;
    box-shadow: 0 4px 12px rgba(0,0,0,.18);
    cursor: pointer;
    border: none;
    transition: transform .15s;
    z-index: 50;
  }
  .fab:hover { transform: scale(1.05); }
  .fab svg { width: 22px; height: 22px; }
  .style-popover {
    position: fixed;
    bottom: 80px;
    right: 320px;
    background: white;
    border: 1px solid var(--border);
    border-radius: 8px;
    padding: 14px;
    box-shadow: 0 8px 28px rgba(0,0,0,.18);
    width: 220px;
    display: none;
    z-index: 60;
  }
  .style-popover.show { display: block; }
  .style-popover h4 {
    margin: 0 0 8px 0;
    font-size: 11px;
    text-transform: uppercase;
    letter-spacing: 1px;
    color: var(--text-dim);
  }
  .color-row { display: flex; gap: 6px; flex-wrap: wrap; margin-bottom: 12px; }
  .swatch {
    width: 22px; height: 22px;
    border-radius: 50%;
    cursor: pointer;
    border: 2px solid transparent;
    transition: transform .12s;
  }
  .swatch:hover { transform: scale(1.1); }
  .swatch.active { border-color: var(--blue); box-shadow: 0 0 0 1px white inset; }
  .size-row { display: flex; align-items: center; gap: 8px; }
  .size-row input[type=range] { flex: 1; accent-color: var(--blue); }
  .size-row .v { font-size: 12px; min-width: 22px; text-align: right; }

  /* Modal */
  .modal-bg {
    position: fixed; inset: 0;
    background: rgba(0,0,0,.4);
    display: none;
    place-items: center;
    z-index: 100;
  }
  .modal-bg.show { display: grid; }
  .modal {
    background: white;
    border-radius: 8px;
    padding: 24px;
    width: 420px;
    max-width: 90vw;
    box-shadow: 0 12px 40px rgba(0,0,0,.25);
  }
  .modal h3 { margin: 0 0 14px 0; font-size: 18px; }
  .modal label {
    display: block;
    font-size: 12px;
    color: var(--text-dim);
    margin-bottom: 4px;
    margin-top: 10px;
    text-transform: uppercase;
    letter-spacing: 0.5px;
  }
  .modal input, .modal select, .modal textarea {
    width: 100%;
    border: 1px solid var(--border);
    padding: 10px 12px;
    border-radius: 4px;
    font-family: inherit;
    font-size: 14px;
    outline: none;
  }
  .modal input:focus, .modal select:focus, .modal textarea:focus { border-color: var(--blue); }
  .modal textarea { resize: vertical; min-height: 80px; }
  .modal-actions { display: flex; gap: 8px; justify-content: flex-end; margin-top: 18px; }
  /* Folder checkbox picker inside the save modal. Scrollable when there
     are lots of folders; max-height keeps the modal a sensible height
     even with 50+ folders. Each row is a full-width clickable label so
     tapping anywhere on the row toggles the checkbox. */
  .modal-folders {
    max-height: 200px;
    overflow-y: auto;
    border: 1px solid var(--border-soft);
    border-radius: 4px;
    padding: 4px;
    background: #fff;
    margin-bottom: 6px;
  }
  .modal-folder-row {
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 5px 8px;
    border-radius: 3px;
    cursor: pointer;
    font-size: 13px;
    user-select: none;
  }
  .modal-folder-row:hover { background: var(--bg-soft); }
  .modal-folder-row input[type="checkbox"] {
    margin: 0;
    flex-shrink: 0;
    cursor: pointer;
  }
  .modal-folder-row span {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
  }
  .modal-folders-empty {
    padding: 10px 8px;
    color: var(--text-dim);
    font-size: 12px;
    font-style: italic;
  }
  #modal-new-folder {
    margin-bottom: 4px;
  }

  /* ------------------------------------------------------------------
     Drill Preview Modal (Quick Look) — 2026-05-26
     ------------------------------------------------------------------
     A wider modal than the save dialog (max 720px) so the big
     thumbnail has room to breathe. Stacks vertically: header / thumb
     / tags / folders / description / actions. Closes via the × button
     in the top-right, click on backdrop, or Escape key. */
  .drill-preview-modal-body {
    width: 720px;
    max-width: 92vw;
    max-height: 90vh;
    overflow-y: auto;
    position: relative;
    padding: 24px;
  }
  .modal-close {
    position: absolute;
    top: 12px;
    right: 12px;
    background: transparent;
    border: none;
    width: 32px;
    height: 32px;
    border-radius: 999px;
    font-size: 22px;
    line-height: 1;
    color: var(--text-dim);
    cursor: pointer;
    transition: background .15s, color .15s;
  }
  .modal-close:hover { background: var(--bg-soft); color: var(--text); }
  .drill-preview-header {
    margin-bottom: 14px;
    padding-right: 36px; /* clear the close button */
  }
  .drill-preview-header h2 {
    margin: 0 0 6px;
    font-size: 22px;
    font-weight: 700;
    color: var(--text);
    line-height: 1.25;
  }
  .drill-preview-meta {
    font-size: 12px;
    color: var(--text-dim);
    line-height: 1.6;
  }
  .drill-preview-meta .dot { margin: 0 6px; color: var(--border); }
  /* Big preview thumbnail — full width of modal, 16:9. */
  .drill-preview-thumb {
    position: relative;
    width: 100%;
    aspect-ratio: 16 / 9;
    border: 1px solid var(--border-soft);
    border-radius: 6px;
    overflow: hidden;
    background: #f4f5f7;
    margin-bottom: 14px;
  }
  .drill-preview-thumb img {
    width: 100%;
    height: 100%;
    object-fit: contain;
    display: block;
  }
  .drill-preview-thumb .anim-badge {
    position: absolute;
    top: 10px;
    right: 10px;
    font-size: 11px;
    padding: 4px 8px;
  }
  .drill-preview-tags,
  .drill-preview-folders {
    display: flex;
    flex-wrap: wrap;
    gap: 6px;
    margin-bottom: 10px;
  }
  .drill-preview-tags .dc-tag,
  .drill-preview-folders .dc-tag {
    max-width: none; /* allow full tag names in the preview, not clipped */
    font-size: 12px;
    padding: 3px 10px;
  }
  .dc-tag--folder {
    background: var(--bg-soft) !important;
    color: var(--text) !important;
  }
  .drill-preview-description {
    border-top: 1px solid var(--border-soft);
    padding-top: 14px;
    margin-bottom: 18px;
    font-size: 14px;
    line-height: 1.55;
    color: var(--text);
    max-height: 40vh;
    overflow-y: auto;
  }
  .drill-preview-description p:first-child { margin-top: 0; }
  .drill-preview-description p:last-child  { margin-bottom: 0; }
  .drill-preview-empty-hint {
    color: var(--text-dim);
    font-size: 12px;
    font-style: italic;
  }

  /* ------------------------------------------------------------------
     Practice Mode — single-drill rink presentation (2026-05-26 rebuild)
     ------------------------------------------------------------------
     The original implementation was a dark projector-style overlay.
     Replaced with the same LIGHT theme + layout idiom as Run Practice
     (on the Plans page) so the two modes feel like siblings. We reuse
     all the .run-* class styles from page_plans — the markup uses
     .run-topbar / .run-body / .run-main / .run-timer-card / etc. —
     and this rule just provides the outer overlay positioning. */
  .practice-mode {
    position: fixed;
    inset: 0;
    z-index: 500;
    background: var(--bg-soft, #f4f5f7);
    color: var(--text);
    display: flex;
    flex-direction: column;
    font-family: inherit;
  }
  .practice-mode[hidden] { display: none; }
  body.practice-mode-open { overflow: hidden; }
  /* Hide the frame-indicator slot when JS hasn't populated it (single
     static drill). Run Practice fills its progress-dot slot per drill;
     for one-drill Practice Mode we only show it when animated. */
  .practice-mode .run-progress:empty { display: none; }
  .practice-header {
    display: flex;
    align-items: flex-start;
    justify-content: space-between;
    padding: 18px 24px 12px;
    border-bottom: 1px solid rgba(255, 255, 255, 0.08);
  }
  .practice-header-left { flex: 1; min-width: 0; }
  .practice-header h1 {
    margin: 0 0 8px;
    font-size: 32px;
    font-weight: 700;
    line-height: 1.2;
    color: #ffffff;
    letter-spacing: -0.01em;
  }
  .practice-tags {
    display: flex;
    flex-wrap: wrap;
    gap: 6px;
  }
  .practice-tag {
    font-size: 13px;
    padding: 3px 10px;
    border-radius: 999px;
    background: rgba(255, 255, 255, 0.12);
    color: #e6eaf2;
  }
  .practice-close {
    background: rgba(255, 255, 255, 0.08);
    border: none;
    color: #ffffff;
    width: 44px;
    height: 44px;
    border-radius: 999px;
    font-size: 24px;
    line-height: 1;
    cursor: pointer;
    transition: background .15s;
    flex-shrink: 0;
    margin-left: 16px;
  }
  .practice-close:hover { background: rgba(255, 255, 255, 0.16); }

  .practice-body {
    flex: 1;
    min-height: 0;
    display: grid;
    grid-template-columns: 1fr 340px;
    gap: 20px;
    padding: 20px 24px 24px;
  }
  /* Vertically narrow viewports (or iPad portrait) — stack rink above
     sidebar so the rink stays the dominant element. */
  @media (max-width: 900px), (orientation: portrait) {
    .practice-body {
      grid-template-columns: 1fr;
      grid-template-rows: minmax(0, 1fr) auto;
    }
  }

  .practice-rink {
    position: relative;
    background: #1a1d22;
    border-radius: 12px;
    overflow: hidden;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 16px;
    min-height: 0;
  }
  .practice-rink img {
    width: 100%;
    height: 100%;
    object-fit: contain;
    display: block;
  }
  .practice-frame-indicator {
    position: absolute;
    top: 14px;
    right: 14px;
    background: rgba(0, 0, 0, 0.6);
    color: #ffffff;
    font-family: inherit;
    font-size: 13px;
    font-weight: 600;
    padding: 4px 10px;
    border-radius: 999px;
    letter-spacing: 0.4px;
  }

  .practice-side {
    display: flex;
    flex-direction: column;
    gap: 16px;
    min-height: 0;
  }
  .practice-timer-card,
  .practice-description-card {
    background: #1a1d22;
    border-radius: 12px;
    padding: 18px 20px;
  }
  .practice-timer-label,
  .practice-description-label {
    font-size: 11px;
    font-weight: 700;
    letter-spacing: 1.4px;
    color: rgba(255, 255, 255, 0.45);
    margin-bottom: 10px;
  }
  .practice-timer {
    font-family: inherit;
    font-size: 64px;
    font-weight: 700;
    line-height: 1;
    color: #ffffff;
    margin-bottom: 14px;
    font-variant-numeric: tabular-nums;
  }
  .practice-timer-card.practice-timer--done {
    background: var(--red, #7c5cff);
    transition: background 0.3s;
  }
  .practice-timer-card.practice-timer--done .practice-timer { color: #fff; }
  .practice-controls {
    display: flex;
    gap: 8px;
  }
  .practice-btn {
    flex: 1;
    padding: 12px 16px;
    border: none;
    border-radius: 8px;
    font-size: 15px;
    font-weight: 600;
    cursor: pointer;
    background: var(--brand-secondary, #1e6fbf);
    color: #ffffff;
    transition: filter .15s, background .15s;
  }
  .practice-btn:hover { filter: brightness(1.1); }
  .practice-btn--ghost {
    background: rgba(255, 255, 255, 0.08);
  }
  .practice-btn--ghost:hover { background: rgba(255, 255, 255, 0.16); }

  .practice-description-card {
    flex: 1;
    min-height: 0;
    display: flex;
    flex-direction: column;
  }
  .practice-description {
    overflow-y: auto;
    flex: 1;
    font-size: 16px;
    line-height: 1.55;
    color: #e6eaf2;
  }
  .practice-description p:first-child { margin-top: 0; }
  .practice-description em { color: rgba(255, 255, 255, 0.5); }

  /* AI "Auto-write" button in the description editor toolbar — small
     pill-shaped button with a star glyph + "AI" label so it visually
     distinguishes from the format buttons next to it. (2026-05-26) */
  .notes-ai-btn {
    display: inline-flex !important;
    align-items: center;
    gap: 4px;
    padding: 4px 10px !important;
    background: color-mix(in srgb, var(--brand-secondary) 12%, #ffffff) !important;
    color: color-mix(in srgb, var(--brand-secondary) 80%, #000000) !important;
    border-radius: 10px !important;
    font-weight: 600;
    font-size: 11px;
    letter-spacing: 0.3px;
  }
  .notes-ai-btn:hover {
    background: color-mix(in srgb, var(--brand-secondary) 20%, #ffffff) !important;
  }
  .notes-ai-btn:disabled {
    opacity: 0.6;
    cursor: progress;
  }
  .notes-ai-btn--loading svg {
    animation: notes-ai-spin 1s linear infinite;
  }
  @keyframes notes-ai-spin { to { transform: rotate(360deg); } }
  .notes-ai-label { line-height: 1; }

  /* AI Coach "Adapt for age" popover — anchored under the Adapt button.
     Light card with chip-style age picker. (Phase 8b 2026-06-14) */
  .notes-ai-adapt-wrap { position: relative; display: inline-block; }
  .notes-ai-adapt-pop {
    position: absolute;
    top: calc(100% + 6px);
    right: 0;
    z-index: 60;
    background: #fff;
    border: 1px solid color-mix(in srgb, var(--brand-secondary) 25%, #d6dae2);
    border-radius: 12px;
    padding: 10px 12px;
    box-shadow: 0 8px 24px rgba(20, 22, 30, 0.12);
    min-width: 220px;
  }
  .notes-ai-adapt-title {
    font-size: 11px;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.5px;
    color: color-mix(in srgb, var(--brand-secondary) 70%, #000);
    margin-bottom: 8px;
  }
  .notes-ai-adapt-chips {
    display: flex;
    flex-wrap: wrap;
    gap: 6px;
  }
  .notes-ai-adapt-chip {
    padding: 5px 10px;
    background: color-mix(in srgb, var(--brand-secondary) 8%, #f4f6fa);
    color: color-mix(in srgb, var(--brand-secondary) 80%, #000);
    border: 1px solid color-mix(in srgb, var(--brand-secondary) 18%, #d6dae2);
    border-radius: 999px;
    font-size: 12px;
    font-weight: 600;
    cursor: pointer;
    transition: background 120ms ease, transform 120ms ease;
  }
  .notes-ai-adapt-chip:hover {
    background: color-mix(in srgb, var(--brand-secondary) 18%, #ffffff);
    transform: translateY(-1px);
  }
  .notes-ai-adapt-chip:disabled {
    opacity: 0.5;
    cursor: progress;
    transform: none;
  }

  /* AI Coach: Plan critique modal — Phase 8b 2026-06-14
     Four labeled sections (summary, strengths, gaps, suggestions) with
     accent-colored bullets. Modal sized for two columns of content but
     collapses to single column on narrow viewports. */
  .plan-editor-critique-btn { color: color-mix(in srgb, var(--brand-secondary) 80%, #000); }
  .plan-editor-critique-btn:hover { background: color-mix(in srgb, var(--brand-secondary) 12%, #fff); }
  .plan-critique-head {
    display: flex;
    align-items: flex-start;
    justify-content: space-between;
    gap: 12px;
    margin-bottom: 12px;
  }
  .plan-critique-name {
    margin-top: 2px;
    font-size: 12px;
    color: var(--text-dim);
  }
  .plan-critique-loading {
    display: flex;
    align-items: center;
    gap: 12px;
    padding: 24px 8px;
    color: var(--text-dim);
  }
  .plan-critique-result { display: flex; flex-direction: column; gap: 16px; }
  .plan-critique-summary {
    padding: 12px 14px;
    background: color-mix(in srgb, var(--brand-secondary) 8%, #f4f6fa);
    border-left: 3px solid var(--brand-secondary);
    border-radius: 6px;
    line-height: 1.4;
  }
  .plan-critique-section {
    border: 1px solid #e3e6ec;
    border-radius: 10px;
    padding: 12px 14px;
  }
  .plan-critique-section h4 {
    margin: 0 0 8px;
    font-size: 12px;
    text-transform: uppercase;
    letter-spacing: 0.6px;
    color: var(--text-dim);
    display: flex;
    align-items: center;
    gap: 6px;
  }
  .plan-critique-section h4::before {
    content: '';
    display: inline-block;
    width: 8px;
    height: 8px;
    border-radius: 50%;
    background: var(--brand-secondary);
  }
  .plan-critique-section--gaps h4::before { background: #e3a83a; }
  .plan-critique-section--suggestions h4::before { background: #22c55e; }
  .plan-critique-section ul {
    margin: 0;
    padding-left: 18px;
    line-height: 1.5;
  }
  .plan-critique-section li { margin-bottom: 4px; }
  .plan-critique-error {
    padding: 12px 14px;
    background: #fde8e6;
    color: #8a2a26;
    border-radius: 6px;
  }

  /* ------------------------------------------------------------------
     Coach Dashboard — 2026-05-26 (visual overhaul)
     ------------------------------------------------------------------
     Hero band with a soft ice-blue gradient holds the greeting + AI
     input as the page's clear focal point. Below the band: calendar
     (above) and widget grid (below) on a clean white canvas with
     accent-coloured iconography so each widget reads as its own
     thing rather than yet-another-grey-box. */
  .dashboard-app {
    min-height: calc(100vh - 52px); /* leave room for the top nav */
    padding: 0 0 80px;
    background: #ffffff;
  }
  .dashboard-wrap {
    /* width:100% matters: .app is a grid, and a grid item with auto
       margins SHRINK-WRAPS to its content instead of stretching — the
       coach view only looked right because the AI card is wide. */
    width: 100%;
    max-width: 1240px;
    margin: 0 auto;
    padding: 0 24px;
  }

  /* Hero band — gradient backdrop. Bleeds full-width via negative
     horizontal margin equal to the wrap padding, then re-applies its
     own inner padding so the AI card sits inside a generous frame. */
  .dashboard-hero {
    position: relative;
    margin: 0 -24px 36px;
    padding: 56px 24px 40px;
    background:
      radial-gradient(circle at 20% 0%, color-mix(in srgb, var(--brand-secondary) 18%, white) 0%, transparent 55%),
      radial-gradient(circle at 90% 100%, color-mix(in srgb, var(--brand-secondary) 12%, white) 0%, transparent 50%),
      linear-gradient(180deg, color-mix(in srgb, var(--brand-secondary) 10%, white) 0%, #ffffff 100%);
    border-bottom: 1px solid var(--border-soft);
  }
  /* Bleeds the hero band to viewport edges on wider screens so it
     reads as a real banner, not a centered card. Updated 2026-05-26
     when the wrap grew from 880 → 1080 to accommodate the 3-up
     widget row. */
  @media (min-width: 1288px) {
    .dashboard-hero {
      margin-left: calc((100vw - 1240px) / -2 + -24px);
      margin-right: calc((100vw - 1240px) / -2 + -24px);
      padding-left: calc((100vw - 1240px) / 2 + 24px);
      padding-right: calc((100vw - 1240px) / 2 + 24px);
    }
  }

  .dashboard-header {
    text-align: center;
    margin-bottom: 24px;
    max-width: 720px;
    margin-left: auto;
    margin-right: auto;
  }
  .dashboard-header h1 {
    font-size: 38px;
    font-weight: 700;
    color: var(--text);
    margin: 0 0 12px;
    letter-spacing: -0.025em;
    line-height: 1.15;
  }
  .dashboard-sub {
    font-size: 17px;
    color: color-mix(in srgb, var(--text) 75%, white);
    margin: 0;
    line-height: 1.5;
    font-weight: 400;
  }

  .dashboard-ai-card {
    background: white;
    border: 1px solid var(--border-soft);
    border-radius: 16px;
    padding: 28px 28px 24px;
    box-shadow: 0 10px 30px -10px rgba(30, 111, 191, 0.18),
                0 4px 12px -2px rgba(0, 0, 0, 0.06);
    max-width: 720px;
    margin: 0 auto;
    transition: box-shadow .2s;
  }
  .dashboard-ai-card:focus-within {
    box-shadow: 0 14px 40px -8px rgba(30, 111, 191, 0.28),
                0 6px 16px -2px rgba(0, 0, 0, 0.08);
  }
  .dashboard-ai-card textarea {
    width: 100%;
    border: none;
    outline: none;
    font-family: inherit;
    font-size: 17px;
    line-height: 1.55;
    color: var(--text);
    resize: none;
    padding: 4px 4px 12px;
    background: transparent;
    letter-spacing: -0.005em;
  }
  .dashboard-ai-card textarea::placeholder { color: var(--text-dim); }
  .dashboard-ai-row {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 12px;
    margin-top: 12px;
    padding-top: 16px;
    border-top: 1px solid var(--border-soft);
  }
  .dashboard-ai-duration {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    font-size: 13px;
    color: var(--text-dim);
  }
  .dashboard-ai-duration select {
    border: 1px solid var(--border-soft);
    border-radius: 6px;
    padding: 6px 8px;
    font-size: 13px;
    color: var(--text);
    background: white;
    cursor: pointer;
  }
  .dashboard-ai-submit {
    border: none;
    background: var(--brand-secondary, #1e6fbf);
    color: white;
    padding: 10px 20px;
    border-radius: 8px;
    font-size: 14px;
    font-weight: 600;
    cursor: pointer;
    transition: filter .12s;
  }
  .dashboard-ai-submit:hover:not(:disabled) { filter: brightness(1.08); }
  .dashboard-ai-submit:disabled { opacity: 0.7; cursor: progress; }

  .dashboard-ai-chips {
    display: flex;
    flex-wrap: wrap;
    gap: 8px;
    margin: 16px auto 0;
    justify-content: center;
    max-width: 720px;
  }
  .dashboard-ai-chip {
    background: rgba(255, 255, 255, 0.7);
    backdrop-filter: blur(8px);
    border: 1px solid color-mix(in srgb, var(--brand-secondary) 18%, white);
    color: color-mix(in srgb, var(--brand-secondary) 80%, #000);
    padding: 7px 14px;
    border-radius: 999px;
    font-size: 12.5px;
    font-weight: 600;
    cursor: pointer;
    transition: background .12s, border-color .12s, transform .12s;
  }
  .dashboard-ai-chip:hover {
    background: white;
    border-color: var(--brand-secondary);
    transform: translateY(-1px);
  }

  .dashboard-ai-loading {
    margin-top: 24px;
    text-align: center;
    color: var(--text-dim);
    font-size: 14px;
  }
  .dashboard-ai-spinner {
    width: 28px;
    height: 28px;
    border-radius: 50%;
    border: 3px solid var(--border-soft);
    border-top-color: var(--brand-secondary, #1e6fbf);
    margin: 0 auto 10px;
    animation: dashboard-ai-spin 0.8s linear infinite;
  }
  @keyframes dashboard-ai-spin { to { transform: rotate(360deg); } }

  .dashboard-ai-error {
    margin-top: 24px;
    padding: 12px 16px;
    background: color-mix(in srgb, var(--red) 8%, white);
    border: 1px solid color-mix(in srgb, var(--red) 40%, white);
    color: color-mix(in srgb, var(--red) 80%, #000);
    border-radius: 8px;
    font-size: 14px;
  }

  /* Generated plan result */
  .dashboard-ai-result {
    margin-top: 28px;
    background: white;
    border: 1px solid var(--border-soft);
    border-radius: 12px;
    padding: 24px;
    box-shadow: 0 1px 3px rgba(0, 0, 0, 0.04);
  }
  .dashboard-ai-result-head { margin-bottom: 8px; }
  .dashboard-ai-result-head h2 {
    margin: 0 0 4px;
    font-size: 22px;
    font-weight: 700;
    color: var(--text);
  }
  .dashboard-ai-result-meta {
    font-size: 13px;
    color: var(--text-dim);
  }
  .dashboard-ai-result-summary {
    font-size: 14px;
    line-height: 1.55;
    color: var(--text);
    margin: 14px 0 18px;
    padding-bottom: 14px;
    border-bottom: 1px solid var(--border-soft);
  }
  .dashboard-ai-result-drills {
    display: flex;
    flex-direction: column;
    gap: 14px;
  }
  .dashboard-ai-drill {
    background: var(--bg-soft);
    border-radius: 8px;
    padding: 14px 16px;
  }
  .dashboard-ai-drill-head {
    display: flex;
    align-items: center;
    gap: 10px;
    margin-bottom: 8px;
  }
  .dashboard-ai-drill-num {
    background: var(--brand-secondary, #1e6fbf);
    color: white;
    border-radius: 999px;
    width: 22px;
    height: 22px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    font-size: 12px;
    font-weight: 700;
    flex-shrink: 0;
  }
  .dashboard-ai-drill-name {
    font-size: 15px;
    font-weight: 600;
    color: var(--text);
    flex: 1;
    min-width: 0;
  }
  .dashboard-ai-drill-mins {
    font-size: 11px;
    font-weight: 600;
    padding: 3px 8px;
    background: white;
    border-radius: 999px;
    color: var(--text-dim);
    flex-shrink: 0;
  }
  .dashboard-ai-drill-objective,
  .dashboard-ai-drill-desc {
    font-size: 13px;
    line-height: 1.5;
    color: var(--text);
    margin-bottom: 6px;
  }
  .dashboard-ai-drill-cues {
    margin: 6px 0 0;
    padding-left: 20px;
    font-size: 13px;
    line-height: 1.5;
    color: var(--text);
  }
  .dashboard-ai-result-actions {
    display: flex;
    gap: 8px;
    justify-content: flex-end;
    margin-top: 20px;
    padding-top: 16px;
    border-top: 1px solid var(--border-soft);
  }

  /* Library-search results (replaces the older generated-plan view).
     Two grouped sections: matched plans on top, matched drills below.
     Each match is a clickable card linking back into /drill?open=ID or
     /plans?open=ID. Empty state lives at the bottom with a fallback CTA.
     2026-05-26 (dashboard revision). */
  .dashboard-ai-hint {
    font-size: 12px;
    color: var(--text-dim);
  }
  .dashboard-results { margin-top: 24px; }
  .dashboard-results-summary {
    font-size: 16px;
    line-height: 1.5;
    color: var(--text);
    margin-bottom: 16px;
    font-weight: 500;
  }
  .dashboard-results-group { margin-bottom: 20px; }
  .dashboard-results-heading {
    display: flex;
    align-items: center;
    gap: 8px;
    font-size: 12px;
    text-transform: uppercase;
    letter-spacing: 0.7px;
    font-weight: 700;
    color: var(--text-dim);
    margin: 0 0 10px;
  }
  .dashboard-results-count {
    background: var(--bg-soft);
    color: var(--text-dim);
    padding: 2px 8px;
    border-radius: 999px;
    font-size: 10px;
    font-weight: 700;
    letter-spacing: 0;
  }
  .dashboard-results-list {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
    gap: 12px;
  }
  .dash-result-card {
    display: flex;
    gap: 12px;
    padding: 10px;
    background: white;
    border: 1px solid var(--border-soft);
    border-radius: 10px;
    cursor: pointer;
    transition: transform .12s, box-shadow .12s, border-color .12s;
    overflow: hidden;
  }
  .dash-result-card:hover {
    transform: translateY(-1px);
    border-color: var(--border);
    box-shadow: 0 4px 12px rgba(0, 0, 0, 0.06);
  }
  .dash-result-thumb {
    position: relative;
    width: 96px;
    height: 56px;
    flex-shrink: 0;
    border-radius: 6px;
    overflow: hidden;
    background: #f4f5f7;
  }
  .dash-result-thumb img {
    width: 100%; height: 100%;
    object-fit: contain;
    display: block;
  }
  .dash-anim-badge {
    position: absolute;
    top: 4px; right: 4px;
    display: inline-flex;
    align-items: center;
    gap: 3px;
    padding: 1px 5px;
    background: rgba(30, 111, 191, 0.95);
    color: white;
    border-radius: 8px;
    font-family: inherit;
    font-size: 9px;
    font-weight: 700;
    line-height: 1;
  }
  .dash-result-plan-icon {
    width: 56px;
    height: 56px;
    flex-shrink: 0;
    background: color-mix(in srgb, var(--brand-secondary) 12%, white);
    color: color-mix(in srgb, var(--brand-secondary) 80%, #000);
    border-radius: 8px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
  }
  .dash-result-info {
    flex: 1;
    min-width: 0;
    display: flex;
    flex-direction: column;
    gap: 4px;
  }
  .dash-result-name {
    font-size: 14px;
    font-weight: 600;
    color: var(--text);
    line-height: 1.3;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
  }
  .dash-result-meta {
    display: flex;
    flex-wrap: wrap;
    gap: 6px;
    font-size: 11px;
    color: var(--text-dim);
  }
  .dash-mins,
  .dash-age {
    background: var(--bg-soft);
    padding: 1px 7px;
    border-radius: 999px;
    font-weight: 600;
    color: var(--text);
  }
  .dash-time { color: var(--text-dim); font-weight: 500; padding: 1px 0; }
  .dash-result-tags {
    display: flex;
    flex-wrap: wrap;
    gap: 4px;
  }
  .dash-tag {
    background: color-mix(in srgb, var(--brand-secondary) 12%, white);
    color: color-mix(in srgb, var(--brand-secondary) 80%, #000);
    padding: 1px 7px;
    border-radius: 999px;
    font-size: 10px;
    font-weight: 500;
    line-height: 1.4;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    max-width: 110px;
  }
  .dashboard-results-suggestion {
    margin-top: 16px;
    padding: 12px 14px;
    background: color-mix(in srgb, var(--brand-secondary) 6%, white);
    border-left: 3px solid var(--brand-secondary);
    border-radius: 4px;
    font-size: 13px;
    line-height: 1.55;
    color: var(--text);
  }
  .dashboard-results-empty {
    margin-top: 16px;
    padding: 32px 20px;
    text-align: center;
    background: white;
    border: 1px dashed var(--border);
    border-radius: 10px;
  }
  .dashboard-results-empty-icon {
    font-size: 32px;
    margin-bottom: 10px;
  }
  .dashboard-results-empty-title {
    font-size: 16px;
    font-weight: 600;
    color: var(--text);
    margin-bottom: 6px;
  }
  .dashboard-results-empty-sub {
    font-size: 13px;
    color: var(--text-dim);
    line-height: 1.5;
    margin-bottom: 16px;
    max-width: 460px;
    margin-left: auto;
    margin-right: auto;
  }

  /* ---- Drill Library page (/library/drills) — 2026-05-26 ----
     Full-page browse view. Same .page wrapper as Plans (max-width
     1240). Layout: left rail with folder navigation + right column
     with search → sort row → roomy responsive card grid. Same visual
     language as dashboard widgets so the product feels coherent. */
  .library-layout {
    display: grid;
    grid-template-columns: 220px 1fr;
    gap: 28px;
    align-items: start;
  }
  @media (max-width: 880px) {
    .library-layout { grid-template-columns: 1fr; gap: 18px; }
  }
  .lib-sidebar {
    display: flex;
    flex-direction: column;
    gap: 18px;
    position: sticky;
    top: 24px;
    align-self: start;
    max-height: calc(100vh - 48px);
    overflow-y: auto;
    padding-right: 4px; /* room for scrollbar without crowding items */
  }
  @media (max-width: 880px) {
    .lib-sidebar {
      position: static;
      max-height: none;
      flex-direction: row;
      overflow-x: auto;
      overflow-y: hidden;
      gap: 8px;
      padding-right: 0;
      -webkit-overflow-scrolling: touch;
    }
  }
  .lib-side-group {
    display: flex;
    flex-direction: column;
    gap: 2px;
  }
  @media (max-width: 880px) {
    .lib-side-group {
      flex-direction: row;
      gap: 6px;
      flex-shrink: 0;
    }
    .lib-side-group + .lib-side-group::before {
      content: '';
      display: inline-block;
      width: 1px;
      align-self: stretch;
      background: var(--border-soft);
      margin: 4px 4px;
    }
  }
  .lib-side-heading {
    font-size: 10.5px;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.7px;
    color: var(--text-dim);
    padding: 8px 8px 4px;
  }
  @media (max-width: 880px) {
    .lib-side-heading { display: none; }
  }
  .lib-side-item {
    appearance: none;
    background: transparent;
    border: 1px solid transparent;
    border-radius: 8px;
    padding: 8px 10px;
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 10px;
    font-size: 13.5px;
    font-weight: 500;
    color: var(--text);
    cursor: pointer;
    text-align: left;
    transition: background .12s, color .12s, border-color .12s;
    font-family: inherit;
    width: 100%;
  }
  .lib-side-item:hover {
    background: var(--bg-soft);
  }
  .lib-side-item.is-active {
    background: color-mix(in srgb, var(--brand-secondary) 12%, white);
    color: color-mix(in srgb, var(--brand-secondary) 80%, #000);
    font-weight: 600;
  }
  .lib-side-item--fav { color: var(--red); }
  .lib-side-item--anim { color: color-mix(in srgb, #1e6fbf 80%, #000); }
  .lib-side-item.is-active.lib-side-item--fav,
  .lib-side-item.is-active.lib-side-item--anim {
    /* Keep the brand-tinted background for actives, regardless of the
       per-row text colour. */
    color: color-mix(in srgb, var(--brand-secondary) 80%, #000);
  }
  .lib-side-label {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    flex: 1;
  }
  .lib-side-count {
    font-size: 11.5px;
    font-weight: 600;
    color: var(--text-dim);
    background: var(--bg-soft);
    border-radius: 999px;
    padding: 1px 8px;
    min-width: 22px;
    text-align: center;
    flex-shrink: 0;
  }
  .lib-side-item.is-active .lib-side-count {
    background: white;
    color: color-mix(in srgb, var(--brand-secondary) 80%, #000);
  }
  @media (max-width: 880px) {
    .lib-side-item {
      flex-shrink: 0;
      padding: 6px 12px;
      font-size: 12.5px;
      border-radius: 999px;
      border: 1px solid var(--border-soft);
      background: white;
    }
    .lib-side-item.is-active {
      background: var(--brand-secondary);
      border-color: var(--brand-secondary);
      color: white;
    }
    .lib-side-item.is-active .lib-side-count {
      background: rgba(255, 255, 255, 0.25);
      color: white;
    }
  }
  .lib-side-empty {
    font-size: 12px;
    color: var(--text-dim);
    padding: 4px 10px 8px;
  }
  @media (max-width: 880px) {
    .lib-side-empty { display: none; }
  }
  .lib-active-label {
    font-size: 18px;
    font-weight: 600;
    color: var(--text);
    flex: 1;
  }

  .library-page .lib-controls {
    margin-bottom: 24px;
    display: flex;
    flex-direction: column;
    gap: 14px;
  }
  .lib-search {
    position: relative;
  }
  .lib-search input {
    width: 100%;
    padding: 12px 14px 12px 42px;
    border: 1px solid var(--border-soft);
    border-radius: 10px;
    background: white;
    font-size: 15px;
    font-family: inherit;
    color: var(--text);
    outline: none;
    transition: border-color .12s, box-shadow .12s;
  }
  .lib-search input:focus {
    border-color: var(--brand-secondary);
    box-shadow: 0 0 0 3px color-mix(in srgb, var(--brand-secondary) 12%, transparent);
  }
  .lib-search-icon {
    position: absolute;
    left: 14px;
    top: 50%;
    transform: translateY(-50%);
    width: 18px;
    height: 18px;
    color: var(--text-dim);
    pointer-events: none;
  }
  .lib-controls-row {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 12px;
    flex-wrap: wrap;
  }
  .lib-filters {
    display: flex;
    flex-wrap: wrap;
    gap: 6px;
  }
  .lib-filter {
    padding: 7px 14px;
    border: 1px solid var(--border-soft);
    background: white;
    color: var(--text);
    border-radius: 999px;
    font-size: 13px;
    font-weight: 600;
    cursor: pointer;
    transition: background .12s, border-color .12s, color .12s;
    font-family: inherit;
  }
  .lib-filter:hover {
    background: var(--bg-soft);
    border-color: var(--border);
  }
  .lib-filter.is-active {
    background: var(--brand-secondary);
    border-color: var(--brand-secondary);
    color: white;
  }
  .lib-sort {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    font-size: 12px;
    color: var(--text-dim);
    flex-shrink: 0;
  }
  .lib-sort-label {
    text-transform: uppercase;
    font-weight: 700;
    letter-spacing: 0.6px;
  }
  .lib-sort-select {
    padding: 7px 10px;
    border: 1px solid var(--border-soft);
    border-radius: 8px;
    background: white;
    font-size: 13px;
    color: var(--text);
    cursor: pointer;
    font-family: inherit;
  }

  /* Card grid — responsive 4-column max on widescreen, scales down. */
  .lib-grid {
    display: grid;
    grid-template-columns: 1fr;
    gap: 18px;
  }
  @media (min-width: 560px) { .lib-grid { grid-template-columns: repeat(2, 1fr); } }
  @media (min-width: 880px) { .lib-grid { grid-template-columns: repeat(3, 1fr); } }
  /* Capped at 3 columns by request (2026-05-26) — at 4 cols the
     thumbnails got too small to read drill diagrams at a glance. */

  .lib-card {
    display: flex;
    flex-direction: column;
    background: white;
    border: 1px solid var(--border-soft);
    border-radius: 14px;
    overflow: hidden;
    text-decoration: none;
    color: var(--text);
    transition: box-shadow .15s, transform .15s, border-color .15s;
    position: relative;
  }
  .lib-card:hover {
    box-shadow: 0 14px 32px -14px rgba(0, 0, 0, 0.16);
    transform: translateY(-2px);
    border-color: var(--border);
  }
  .lib-card-thumb {
    position: relative;
    aspect-ratio: 16 / 10;
    background: var(--bg-soft);
    overflow: hidden;
  }
  .lib-card-thumb img {
    width: 100%;
    height: 100%;
    object-fit: contain;
    display: block;
  }
  .lib-card-thumb--loading {
    background: #f4f5f7;
  }
  .lib-card-thumb--loading::after {
    content: '';
    position: absolute;
    inset: 0;
    background:
      center / 22px 22px no-repeat
      url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><circle cx='12' cy='12' r='9' fill='none' stroke='%23e7e9ec' stroke-width='2.5'/><path d='M12 3 a 9 9 0 0 1 9 9' fill='none' stroke='%23d4302b' stroke-width='2.5' stroke-linecap='round'/></svg>");
    animation: drill-thumb-spin 0.8s linear infinite;
    pointer-events: none;
  }
  .lib-card-anim {
    position: absolute;
    top: 10px;
    left: 10px;
    display: inline-flex;
    align-items: center;
    gap: 4px;
    padding: 3px 8px;
    background: rgba(30, 111, 191, 0.95);
    color: white;
    border-radius: 999px;
    font-size: 10px;
    font-weight: 700;
    font-family: inherit;
    line-height: 1;
    box-shadow: 0 2px 6px rgba(0, 0, 0, 0.2);
  }
  .lib-card-fav {
    position: absolute;
    top: 8px;
    right: 8px;
    width: 32px;
    height: 32px;
    border-radius: 999px;
    border: none;
    background: rgba(255, 255, 255, 0.92);
    color: var(--text-dim);
    display: inline-flex;
    align-items: center;
    justify-content: center;
    cursor: pointer;
    backdrop-filter: blur(4px);
    transition: color .12s, background .12s, transform .12s;
    box-shadow: 0 2px 8px rgba(0, 0, 0, 0.12);
  }
  .lib-card-fav:hover { color: var(--red); transform: scale(1.08); }
  .lib-card-fav--on { color: var(--red); }

  /* Selection checkbox — top-left, mirrors the fav star on the right.
     Fades in on hover or whenever the card is selected so unselected
     cards stay visually clean. */
  .lib-card-check {
    position: absolute;
    top: 8px;
    left: 8px;
    width: 28px;
    height: 28px;
    border-radius: 8px;
    border: none;
    background: rgba(255, 255, 255, 0.92);
    color: var(--text-dim);
    display: inline-flex;
    align-items: center;
    justify-content: center;
    cursor: pointer;
    backdrop-filter: blur(4px);
    transition: opacity .12s, color .12s, background .12s, transform .12s;
    box-shadow: 0 2px 8px rgba(0, 0, 0, 0.12);
    opacity: 0;
  }
  .lib-card:hover .lib-card-check,
  .lib-card-check--on,
  .lib-card.is-selected .lib-card-check {
    opacity: 1;
  }
  .lib-card-check:hover { transform: scale(1.08); }
  .lib-card-check--on {
    background: var(--brand-secondary);
    color: white;
  }
  .lib-card.is-selected {
    border-color: var(--brand-secondary);
    box-shadow: 0 0 0 2px color-mix(in srgb, var(--brand-secondary) 35%, transparent);
  }
  .lib-card.is-selected:hover {
    box-shadow: 0 0 0 2px color-mix(in srgb, var(--brand-secondary) 50%, transparent),
                0 14px 32px -14px rgba(0, 0, 0, 0.16);
  }

  /* Floating bottom action bar — appears when at least one drill is
     selected. Shows the count + Clear + "Open in Drill Board" CTA. */
  .lib-selection-bar {
    position: fixed;
    bottom: 24px;
    left: 50%;
    transform: translateX(-50%);
    display: flex;
    align-items: center;
    gap: 12px;
    padding: 10px 14px;
    background: var(--text);
    color: white;
    border-radius: 999px;
    box-shadow: 0 12px 40px -10px rgba(0, 0, 0, 0.45);
    z-index: 100;
    animation: lib-sel-bar-in 0.18s ease-out;
  }
  @keyframes lib-sel-bar-in {
    from { opacity: 0; transform: translate(-50%, 14px); }
    to   { opacity: 1; transform: translate(-50%, 0); }
  }
  .lib-selection-count {
    font-size: 13.5px;
    font-weight: 600;
    padding: 0 6px;
  }
  .lib-selection-bar .btn {
    padding: 7px 14px;
    font-size: 13px;
    border-radius: 999px;
  }
  .lib-selection-bar .btn-secondary {
    background: rgba(255, 255, 255, 0.12);
    color: white;
    border: 1px solid rgba(255, 255, 255, 0.18);
  }
  .lib-selection-bar .btn-secondary:hover {
    background: rgba(255, 255, 255, 0.22);
  }
  .lib-selection-bar .btn-primary {
    background: var(--brand-secondary);
    border: none;
  }

  /* Add-to-plan modal — list of existing plans + an inline "new plan"
     creator. Sized for a comfortable browse of ~6 plans before scrolling. */
  .lib-addplan-modal {
    width: 480px;
    max-width: 92vw;
  }
  .lib-addplan-new {
    display: flex;
    gap: 8px;
    margin-bottom: 16px;
  }
  .lib-addplan-new input {
    flex: 1;
    padding: 10px 12px;
    border: 1px solid var(--border-soft);
    border-radius: 8px;
    font-size: 14px;
    font-family: inherit;
    color: var(--text);
    outline: none;
  }
  .lib-addplan-new input:focus {
    border-color: var(--brand-secondary);
    box-shadow: 0 0 0 3px color-mix(in srgb, var(--brand-secondary) 12%, transparent);
  }
  .lib-addplan-new .btn-primary {
    flex-shrink: 0;
    white-space: nowrap;
  }
  .lib-addplan-divider {
    display: flex;
    align-items: center;
    gap: 10px;
    margin: 6px 0 12px;
    color: var(--text-dim);
    font-size: 11.5px;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.6px;
  }
  .lib-addplan-divider::before,
  .lib-addplan-divider::after {
    content: '';
    flex: 1;
    height: 1px;
    background: var(--border-soft);
  }
  .lib-addplan-list {
    max-height: 340px;
    overflow-y: auto;
    display: flex;
    flex-direction: column;
    gap: 4px;
    margin-bottom: 4px;
  }
  .lib-addplan-row {
    appearance: none;
    background: white;
    border: 1px solid var(--border-soft);
    border-radius: 10px;
    padding: 12px 14px;
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 10px;
    text-align: left;
    cursor: pointer;
    font-family: inherit;
    transition: background .12s, border-color .12s;
  }
  .lib-addplan-row:hover {
    background: var(--bg-soft);
    border-color: var(--border);
  }
  .lib-addplan-row-name {
    font-size: 14.5px;
    font-weight: 600;
    color: var(--text);
    line-height: 1.3;
  }
  .lib-addplan-row-meta {
    font-size: 12px;
    color: var(--text-dim);
    margin-top: 2px;
  }
  .lib-addplan-overlap {
    font-size: 11px;
    color: var(--text-dim);
    background: var(--bg-soft);
    border-radius: 999px;
    padding: 3px 9px;
    font-weight: 600;
    flex-shrink: 0;
  }
  .lib-addplan-empty {
    padding: 24px 14px;
    text-align: center;
    color: var(--text-dim);
    font-size: 13px;
  }
  .lib-card-info {
    padding: 14px 16px 16px;
    display: flex;
    flex-direction: column;
    gap: 6px;
    flex: 1;
  }
  .lib-card-name {
    font-size: 15px;
    font-weight: 600;
    color: var(--text);
    line-height: 1.3;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
  }
  .lib-card-meta {
    display: flex;
    flex-wrap: wrap;
    gap: 6px;
    align-items: center;
    font-size: 11px;
    color: var(--text-dim);
  }
  .lib-mins,
  .lib-age {
    background: var(--bg-soft);
    padding: 2px 8px;
    border-radius: 999px;
    font-weight: 600;
    color: var(--text);
  }
  .lib-plans {
    color: color-mix(in srgb, var(--brand-secondary) 80%, #000);
    font-weight: 600;
  }
  .lib-time { color: var(--text-dim); font-weight: 500; }
  .lib-card-tags {
    display: flex;
    flex-wrap: wrap;
    gap: 4px;
    margin-top: 2px;
  }
  .lib-tag {
    background: color-mix(in srgb, var(--brand-secondary) 12%, white);
    color: color-mix(in srgb, var(--brand-secondary) 80%, #000);
    padding: 2px 8px;
    border-radius: 999px;
    font-size: 10.5px;
    font-weight: 500;
    line-height: 1.5;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    max-width: 120px;
  }
  .lib-tag--more {
    background: var(--bg-soft);
    color: var(--text-dim);
    max-width: none;
  }

  .lib-empty {
    text-align: center;
    padding: 60px 20px;
  }
  .lib-empty-icon {
    font-size: 40px;
    margin-bottom: 12px;
  }
  .lib-empty-title {
    font-size: 17px;
    font-weight: 600;
    color: var(--text);
    margin-bottom: 6px;
  }
  .lib-empty-sub {
    font-size: 13px;
    color: var(--text-dim);
  }

  /* ---- 7-day calendar strip (2026-05-26, visual overhaul) ---- */
  /* Calendar sits ABOVE the hero — first thing the coach sees. Each day
     cell is taller now, with the day-of-week label tucked at the top in
     muted weight and the date number as the dominant glyph. Today's
     cell gets a brand-coloured fill (not a stroke) so it pops; days
     with events show a tinted bottom rail in the event's colour. */
  .dash-cal {
    display: grid;
    grid-template-columns: repeat(7, 1fr);
    /* Roomier gutters between day cells — was 8px, felt cramped on
       wider screens where each cell is taller. (2026-05-26) */
    gap: 14px;
    padding: 32px 8px 8px;
    margin-bottom: 0;
    /* Stacking-context lift — the hero band below has its own
       stacking context (background gradient + position:relative) and
       was painting OVER the absolutely-positioned tooltips that
       extend out of calendar cells. Putting the calendar on its own
       higher z-index plane makes its tooltips render above siblings.
       (2026-05-26 fix.) */
    position: relative;
    z-index: 10;
  }
  .dash-cal-day {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 4px;
    padding: 10px 4px 8px;
    background: white;
    border: 1px solid var(--border-soft);
    border-radius: 12px;
    color: var(--text);
    text-decoration: none;
    transition: background .12s, border-color .12s, transform .12s, box-shadow .12s;
    position: relative;
    /* overflow:visible (not hidden) so the absolutely-positioned
       .dash-cal-tip tooltip can extend below the cell on hover. */
    overflow: visible;
  }
  .dash-cal-day:hover {
    background: var(--bg-soft);
    border-color: var(--border);
    transform: translateY(-2px);
    box-shadow: 0 6px 16px -6px rgba(0, 0, 0, 0.12);
  }
  .dash-cal-day.is-today {
    background: var(--brand-secondary, #1e6fbf);
    border-color: var(--brand-secondary, #1e6fbf);
    box-shadow: 0 8px 20px -8px rgba(30, 111, 191, 0.55);
  }
  .dash-cal-day.is-today .dash-cal-dow,
  .dash-cal-day.is-today .dash-cal-num {
    color: white;
  }
  .dash-cal-day.is-today:hover {
    transform: translateY(-3px);
    filter: brightness(1.05);
  }
  .dash-cal-dow {
    font-size: 11px;
    font-weight: 700;
    letter-spacing: 0.6px;
    text-transform: uppercase;
    color: var(--text-dim);
  }
  .dash-cal-num {
    font-size: 22px;
    font-weight: 700;
    line-height: 1.05;
    color: var(--text);
    letter-spacing: -0.02em;
  }
  .dash-cal-dots {
    display: flex;
    gap: 3px;
    height: 6px;
    margin-top: 4px;
  }
  .dash-cal-dot {
    width: 6px;
    height: 6px;
    border-radius: 50%;
    background: var(--text-dim);
  }
  .dash-cal-dot--game     { background: var(--red, #7c5cff); }
  .dash-cal-dot--practice { background: var(--brand-secondary, #1e6fbf); }
  .dash-cal-dot--event    { background: #94a3b8; }
  /* When today has events, swap the dots for white so they show on
     the blue background. */
  .dash-cal-day.is-today .dash-cal-dot {
    background: rgba(255, 255, 255, 0.85);
  }

  /* Calendar tooltip — hover-only affordance for desktop, surfacing the
     date + event list without forcing a navigation. iPad coaches tap to
     navigate to /schedule for the same info, since hover-only tooltips
     are unreliable under touch. position: absolute against the day cell;
     side modifiers nudge the leftmost / rightmost cells' tooltips inward
     so they don't clip off the viewport. */
  .dash-cal-tip {
    position: absolute;
    top: calc(100% + 8px);
    left: 50%;
    transform: translateX(-50%) translateY(-4px);
    min-width: 200px;
    max-width: 280px;
    padding: 12px 14px;
    background: var(--panel-dark, #2c3036);
    color: #f5f7fa;
    border-radius: 10px;
    box-shadow: 0 12px 28px -8px rgba(0, 0, 0, 0.35);
    opacity: 0;
    pointer-events: none;
    transition: opacity .15s, transform .15s;
    /* High z-index lifts the tooltip above sibling stacking contexts
       below (the hero band). Combined with `.dash-cal` having its own
       z-index:10, this guarantees the tooltip paints over the hero. */
    z-index: 100;
    text-align: left;
    line-height: 1.4;
    /* Small arrow pointing up at the day cell. */
  }
  .dash-cal-tip::before {
    content: '';
    position: absolute;
    bottom: 100%;
    left: 50%;
    transform: translateX(-50%);
    border: 6px solid transparent;
    border-bottom-color: var(--panel-dark, #2c3036);
  }
  .dash-cal-day:hover .dash-cal-tip,
  .dash-cal-day:focus-visible .dash-cal-tip {
    opacity: 1;
    transform: translateX(-50%) translateY(0);
  }
  /* Left-edge cell — pin tooltip to the left edge of the cell + move
     the arrow accordingly so it stays visible. */
  .dash-cal-day--tip-left .dash-cal-tip {
    left: 0;
    transform: translateX(0) translateY(-4px);
  }
  .dash-cal-day--tip-left:hover .dash-cal-tip,
  .dash-cal-day--tip-left:focus-visible .dash-cal-tip {
    transform: translateX(0) translateY(0);
  }
  .dash-cal-day--tip-left .dash-cal-tip::before {
    left: 18px;
    transform: translateX(0);
  }
  .dash-cal-day--tip-right .dash-cal-tip {
    left: auto;
    right: 0;
    transform: translateX(0) translateY(-4px);
  }
  .dash-cal-day--tip-right:hover .dash-cal-tip,
  .dash-cal-day--tip-right:focus-visible .dash-cal-tip {
    transform: translateX(0) translateY(0);
  }
  .dash-cal-day--tip-right .dash-cal-tip::before {
    left: auto;
    right: 18px;
    transform: translateX(0);
  }
  .dash-cal-tip-head {
    font-size: 12px;
    font-weight: 700;
    letter-spacing: 0.4px;
    text-transform: uppercase;
    color: rgba(255, 255, 255, 0.6);
    margin-bottom: 6px;
  }
  .dash-cal-tip-empty {
    font-size: 12px;
    color: rgba(255, 255, 255, 0.55);
    font-style: italic;
  }
  .dash-cal-tip-list {
    display: flex;
    flex-direction: column;
    gap: 6px;
  }
  .dash-cal-tip-row {
    display: flex;
    align-items: center;
    gap: 8px;
    font-size: 13px;
    color: #f5f7fa;
  }
  .dash-cal-tip-dot {
    width: 7px;
    height: 7px;
    border-radius: 50%;
    flex-shrink: 0;
    background: rgba(255, 255, 255, 0.5);
  }
  .dash-cal-tip-dot--game     { background: var(--red, #7c5cff); }
  .dash-cal-tip-dot--practice { background: var(--brand-secondary, #1e6fbf); }
  .dash-cal-tip-dot--event    { background: #94a3b8; }
  .dash-cal-tip-label {
    flex: 1;
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    font-weight: 500;
  }
  .dash-cal-tip-time {
    font-size: 11px;
    color: rgba(255, 255, 255, 0.7);
    font-family: inherit;
    font-weight: 600;
    flex-shrink: 0;
  }

  /* ---- Widget grid — accent-coloured per widget for personality ----
     Stack on narrow viewports; force a 3-up row on tablet+ widths so
     the three widgets sit side-by-side across the page like Ian asked
     (auto-fit was happy to wrap when content nudged past min-width).
     2026-05-26. */
  .dash-widgets {
    display: grid;
    grid-template-columns: 1fr;
    gap: 14px;
    margin-top: 8px;
    margin-bottom: 8px;
  }
  @media (min-width: 720px) {
    .dash-widgets { grid-template-columns: repeat(3, 1fr); }
  }
  .dash-widget {
    background: white;
    border: 1px solid var(--border-soft);
    border-radius: 14px;
    padding: 18px 18px 14px;
    transition: box-shadow .15s, transform .15s, border-color .15s;
    position: relative;
    overflow: hidden;
  }
  .dash-widget:hover {
    box-shadow: 0 12px 28px -12px rgba(0, 0, 0, 0.14);
    transform: translateY(-2px);
  }
  /* Top accent ribbon — 3px coloured strip flush with the top of the
     card, scoped per widget so each one reads as its own thing. */
  .dash-widget::before {
    content: '';
    position: absolute;
    top: 0; left: 0; right: 0;
    height: 3px;
    background: var(--text-dim);
    opacity: 0.7;
  }
  .dash-widget--recent::before { background: var(--brand-secondary, #1e6fbf); }
  .dash-widget--fav::before    { background: #f5a524; }
  .dash-widget--upnext::before { background: var(--red, #7c5cff); }

  .dash-widget-head {
    display: flex;
    align-items: center;
    gap: 8px;
    margin-bottom: 12px;
  }
  .dash-widget-icon {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 24px;
    height: 24px;
    border-radius: 6px;
    flex-shrink: 0;
  }
  .dash-widget--recent .dash-widget-icon {
    background: color-mix(in srgb, var(--brand-secondary) 14%, white);
    color: color-mix(in srgb, var(--brand-secondary) 80%, #000);
  }
  .dash-widget--fav .dash-widget-icon {
    background: color-mix(in srgb, #f5a524 18%, white);
    color: color-mix(in srgb, #f5a524 75%, #000);
  }
  .dash-widget--upnext .dash-widget-icon {
    background: color-mix(in srgb, var(--red) 12%, white);
    color: color-mix(in srgb, var(--red) 80%, #000);
  }
  .dash-widget-head h3 {
    font-size: 12px;
    text-transform: uppercase;
    letter-spacing: 0.7px;
    font-weight: 700;
    color: var(--text);
    margin: 0;
    flex: 1;
  }
  .dash-widget-more {
    font-size: 11px;
    color: var(--text-dim);
    text-decoration: none;
    font-weight: 600;
    transition: color .12s;
  }
  .dash-widget-more:hover { color: var(--brand-secondary); text-decoration: underline; }
  .dash-widget-list {
    display: flex;
    flex-direction: column;
    gap: 4px;
  }
  .dash-widget-row {
    display: flex;
    align-items: center;
    gap: 12px;
    padding: 8px 8px;
    border-radius: 8px;
    text-decoration: none;
    color: var(--text);
    transition: background .12s, transform .12s;
  }
  .dash-widget-row:hover {
    background: var(--bg-soft);
    transform: translateX(2px);
  }
  /* Thumbnails were 36×24 — too small to actually read. Bumped to a
     proper 16:9 preview so coaches can recognise a drill at a glance
     from the dashboard widgets. (2026-05-26) */
  .dash-widget-thumb {
    width: 80px;
    height: 50px;
    border-radius: 6px;
    object-fit: contain;
    background: var(--bg-soft);
    flex-shrink: 0;
    border: 1px solid var(--border-soft);
  }
  .dash-widget-row-name {
    flex: 1;
    min-width: 0;
    font-size: 14px;
    font-weight: 500;
    line-height: 1.3;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
  }
  .dash-widget-row-mins {
    font-size: 11px;
    font-weight: 600;
    color: var(--text-dim);
    flex-shrink: 0;
    padding: 2px 8px;
    background: var(--bg-soft);
    border-radius: 999px;
  }
  .dash-widget-cal-icon {
    width: 50px;
    height: 50px;
    border-radius: 8px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    font-size: 18px;
    font-weight: 700;
    color: white;
    background: var(--text-dim);
    flex-shrink: 0;
  }
  .dash-widget-cal-icon--game     { background: var(--red, #7c5cff); }
  .dash-widget-cal-icon--practice { background: var(--brand-secondary, #1e6fbf); }
  .dash-widget-cal-icon--event    { background: #888; }
  .dash-widget-empty {
    padding: 8px 8px 4px;
    font-size: 12px;
    color: var(--text-dim);
    font-style: italic;
    line-height: 1.4;
  }
  .btn {
    border: 1px solid var(--border);
    background: white;
    padding: 8px 16px;
    border-radius: 4px;
    cursor: pointer;
    font-family: inherit;
    font-size: 14px;
  }
  .btn:hover { background: var(--bg-soft); }
  .btn-primary { background: var(--brand-secondary); color: white; border-color: var(--brand-secondary); }
  .btn-primary:hover { filter: brightness(0.92); }
  .btn-danger { background: var(--red); color: white; border-color: var(--red); transition: filter .15s; }
  /* Restate the background on hover/focus so the generic `.btn:hover` rule above
     can't repaint the button to var(--bg-soft) — that would defeat the filter. */
  .btn-danger:hover, .btn-danger:focus { background: var(--red); filter: brightness(0.9); }
  /* All primary buttons get the same darken-on-hover treatment. */
  .btn-primary, .login-form button, .goalie-section, .plan-btn, .nav-drawer-link.active, .topnav-link.active {
    transition: filter .15s, background .15s;
  }
  .btn-primary:hover, .btn-primary:focus { background: var(--brand-secondary); filter: brightness(0.9); }
  .login-form button:hover, .login-form button:focus { background: var(--brand-primary); filter: brightness(0.9); }
  .nav-drawer-link.active:hover, .nav-drawer-link.active:focus { background: var(--brand-primary); filter: brightness(0.9); }
  .topnav-link.active:hover, .topnav-link.active:focus { background: var(--brand-primary); filter: brightness(0.9); }

  /* Drill picker for plan */
  .drill-picker {
    max-height: 320px;
    overflow-y: auto;
    border: 1px solid var(--border-soft);
    border-radius: 4px;
    margin: 8px 0;
  }
  .drill-picker .pick-item {
    padding: 8px 12px;
    cursor: pointer;
    display: flex;
    gap: 10px;
    align-items: center;
    border-bottom: 1px solid var(--border-soft);
  }
  .drill-picker .pick-item:hover { background: var(--bg-soft); }
  .drill-picker .pick-item:last-child { border-bottom: none; }
  .drill-picker .pick-item img {
    width: 60px; height: 32px;
    border: 1px solid var(--border-soft);
    border-radius: 3px;
  }
  .drill-picker .pick-item .nm { flex: 1; font-size: 13px; }

  /* Toast — Emil polish: explicit properties + custom ease-out curve,
     subtle scale on entry so it materializes rather than just slides. */
  .toast {
    position: fixed;
    bottom: 24px;
    left: 50%;
    transform: translateX(-50%) translateY(20px) scale(0.96);
    background: var(--panel-dark);
    color: white;
    padding: 10px 18px;
    border-radius: 4px;
    font-size: 13px;
    opacity: 0;
    transition:
      transform 220ms cubic-bezier(0.23, 1, 0.32, 1),
      opacity 220ms ease-out;
    z-index: 200;
    pointer-events: none;
    box-shadow: 0 6px 18px rgba(0,0,0,.2);
  }
  .toast.show {
    opacity: 1;
    transform: translateX(-50%) translateY(0) scale(1);
  }
  @media (prefers-reduced-motion: reduce) {
    .toast { transition: opacity 180ms ease-out; transform: translateX(-50%) translateY(0); }
    .toast.show { transform: translateX(-50%) translateY(0); }
  }

  ::-webkit-scrollbar { width: 8px; height: 8px; }
  ::-webkit-scrollbar-track { background: transparent; }
  ::-webkit-scrollbar-thumb { background: var(--border); border-radius: 4px; }
  ::-webkit-scrollbar-thumb:hover { background: #b0b6bd; }

  @media (max-width: 1100px) {
    main { grid-template-columns: 120px 1fr 280px; }
    .drill-name { width: 220px; }
  }
  @media (max-width: 800px) {
    /* On non-drill pages, narrow screens drop the docked sidebar and the
       page takes the full width. (A legacy `main { grid-template-columns:
       110px 1fr }` here predated the plans editor's own <main> and was
       crushing it to a 110px column on phones — the only non-drill <main>
       left is the plans editor, which manages its own grid.) */
    body:not(.route-drill) .sidebar { display: none; }
    .fab { right: 24px; }
    .style-popover { right: 24px; }
  }

/* ============================================================
   PHASE 4 — TOP NAV + MULTI-PAGE CHROME
   ============================================================ */
.topnav {
  display: flex; align-items: center; gap: 18px;
  /* Inset by env(safe-area-inset-*) so the bar respects the notch /
     Dynamic Island in landscape iOS, and the rounded corners on
     Android. Padding-left + right matter most in landscape; top
     handles a status-bar overlap if the app is ever in fullscreen. */
  padding:
    env(safe-area-inset-top, 0)
    calc(16px + env(safe-area-inset-right, 0))
    0
    calc(16px + env(safe-area-inset-left, 0));
  height: calc(52px + env(safe-area-inset-top, 0));
  background: var(--panel-dark);
  color: #fff;
  border-bottom: 1px solid #1a1d22;
  position: sticky; top: 0; z-index: 90;
}
.topnav .brand {
  display: inline-flex; align-items: center; gap: 8px;
  color: #fff; text-decoration: none;
  font-weight: 700; letter-spacing: 0.4px;
}
.topnav .brand-mark {
  width: 28px; height: 28px;
  border-radius: 50%;
  background: var(--brand-primary);
  display: grid; place-items: center;
  font-weight: 700; font-size: 14px;
  overflow: hidden;
  color: #fff;
}
.topnav .brand-mark img {
  width: 100%; height: 100%;
  object-fit: cover;
  display: block;
}
.topnav .brand-text { font-size: 15px; }
.topnav-links { display: flex; gap: 2px; flex: 1; overflow-x: auto; }
.topnav-link {
  padding: 8px 14px;
  color: #d6d9de;
  text-decoration: none;
  font-size: 13px;
  font-weight: 500;
  border-radius: 6px;
  white-space: nowrap;
  transition: background .12s, color .12s;
}
.topnav-link:hover { background: rgba(255,255,255,.06); color: #fff; }
.topnav-link.active { background: var(--brand-primary); color: #fff; }
.topnav-right { display: flex; align-items: center; gap: 10px; }
.team-chip {
  position: relative;
  display: inline-flex; align-items: center; gap: 6px;
  background: rgba(255,255,255,.08);
  color: #fff;
  padding: 6px 12px;
  border-radius: 16px;
  font-size: 13px;
  cursor: pointer;
  user-select: none;
}
.team-chip:hover { background: rgba(255,255,255,.14); }
.team-chip .team-name { max-width: 140px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.team-menu {
  position: absolute; top: 100%; right: 0; margin-top: 6px;
  background: #fff; color: var(--text);
  border-radius: 6px;
  box-shadow: 0 8px 28px rgba(0,0,0,.25);
  min-width: 220px;
  display: none;
  z-index: 95;
}
.team-menu.show { display: block; }
.team-menu .item {
  padding: 10px 14px;
  cursor: pointer;
  font-size: 13px;
  display: flex; align-items: center; justify-content: space-between;
}
.team-menu .item:hover { background: var(--bg-soft); }
.team-menu .item.active { font-weight: 600; color: var(--red); }
.team-menu .item.action { color: var(--blue); }
.team-menu .badge {
  background: var(--bg-soft);
  color: var(--text-dim);
  font-size: 10px;
  text-transform: uppercase;
  padding: 2px 6px;
  border-radius: 8px;
}
.team-menu .divider { height: 1px; background: var(--border-soft); margin: 4px 0; }
.logout-btn {
  background: transparent; color: #d6d9de;
  border: 1px solid rgba(255,255,255,.18);
  padding: 6px 12px; border-radius: 6px;
  font-size: 12px; cursor: pointer;
}
.logout-btn:hover { background: rgba(255,255,255,.08); color: #fff; }

/* Main page container (everything that isn't the drill route) */
.page-main { min-height: calc(100vh - 52px); }
body.route-drill .page-main { height: calc(100vh - 52px); }

/* Give the canvas most of the visible viewport, then let tags + notes spill
   below the fold. Scroll inside .canvas-wrap to reach them. The 220px chrome
   allowance covers the drill-tabs strip + the style bar + .canvas-wrap padding;
   tweak if any of those grow. Mobile keeps its own rules in the @media block. */
body.route-drill .canvas-wrap { overflow-y: auto; overflow-x: hidden; }
body.route-drill .canvas-stage { min-height: calc(100vh - 220px); }

/* Generic content shells for the non-drill pages */
.page {
  max-width: 1240px;
  margin: 0 auto;
  padding: 32px 24px 60px;
}
.page-header {
  display: flex; align-items: flex-end; justify-content: space-between;
  flex-wrap: wrap;
  gap: 16px;
  margin-bottom: 28px;
  padding-bottom: 20px;
  border-bottom: 1px solid var(--border-soft);
}
.page-header h1 {
  margin: 0;
  font-size: 30px;
  font-weight: 700;
  letter-spacing: -0.02em;
  line-height: 1.15;
}
.page-header .sub {
  color: var(--text-dim);
  font-size: 14px;
  margin-top: 6px;
  line-height: 1.5;
}
.page-actions { display: flex; gap: 8px; flex-wrap: wrap; }
.page-actions .btn { font-size: 13px; }

.card {
  background: #fff;
  border: 1px solid var(--border-soft);
  border-radius: 8px;
  padding: 16px;
  margin-bottom: 12px;
  box-shadow: 0 1px 2px rgba(0,0,0,.03);
}
.card .card-head {
  display: flex; align-items: center; justify-content: space-between;
  gap: 10px;
  margin-bottom: 8px;
}
.card h2 { margin: 0; font-size: 15px; font-weight: 600; }

.empty {
  text-align: center;
  padding: 56px 20px;
  color: var(--text-dim);
}
.empty .icon { font-size: 36px; margin-bottom: 8px; }

table.data-table {
  width: 100%;
  border-collapse: collapse;
  font-size: 13px;
}
table.data-table th, table.data-table td {
  text-align: left;
  padding: 9px 10px;
  border-bottom: 1px solid var(--border-soft);
  vertical-align: middle;
}
table.data-table th {
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.5px;
  font-size: 11px;
  color: var(--text-dim);
  background: var(--bg-soft);
}
table.data-table tr:hover td { background: #fafbfc; }
table.data-table input[type="number"], table.data-table input[type="text"] {
  width: 100%; padding: 4px 6px; font-size: 13px;
  border: 1px solid var(--border-soft); border-radius: 4px;
}
table.data-table input[type="number"]:focus, table.data-table input[type="text"]:focus {
  border-color: var(--blue); outline: none;
}

.pos-group { margin-bottom: 18px; }
.pos-group h3 {
  font-size: 11px; text-transform: uppercase; letter-spacing: 0.8px;
  color: var(--text-dim); margin: 6px 0 6px;
}

.kv { display: grid; grid-template-columns: 120px 1fr; gap: 8px 12px; font-size: 13px; }
.kv .k { color: var(--text-dim); }

/* Page-specific tweaks */
body.route-drill .topnav { /* already correct */ }
body:not(.route-drill) .fab { display: none; }

/* ============================================================
   SHOT TRACKER
   ============================================================ */
.shot-modal-content {
  width: min(1500px, 98vw) !important;
  max-height: 94vh;
  display: flex;
  flex-direction: column;
}
.shot-modal-header {
  display: flex; align-items: center; justify-content: space-between;
  gap: 12px 20px;
  flex-wrap: wrap;
  margin-bottom: 8px;
}
.gc-clock { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
.gc-clock .shot-goalie-select { width: auto; flex: 0 0 auto; }
.gc-clock-period {
  font-size: 12px; font-weight: 800; text-transform: uppercase;
  color: var(--text-dim); letter-spacing: .4px;
}
.gc-clock-time {
  font-size: 34px; font-weight: 800; font-variant-numeric: tabular-nums;
  min-width: 104px; text-align: center; cursor: pointer;
  padding: 2px 8px; border-radius: 8px;
}
.gc-clock-time:hover { background: var(--bg-soft); }
.gc-clock-time.running { color: var(--brand-primary, var(--red)); }
.shot-modal-header h3 { margin: 0; }
.shot-modal-header .sub { font-size: 12px; color: var(--text-dim); }
.shot-modal-toolbar {
  display: flex; gap: 10px 16px; align-items: center;
  flex-wrap: wrap;
  padding: 10px 12px;
  background: var(--bg-soft);
  border-radius: 6px;
  margin-bottom: 12px;
}
.shot-mode-toggle {
  display: inline-flex;
  background: #fff;
  border: 1px solid var(--border);
  border-radius: 20px;
  padding: 2px;
}
.shot-mode-toggle .mode-btn {
  background: transparent;
  border: none;
  padding: 6px 18px;
  border-radius: 16px;
  font-size: 13px;
  font-weight: 500;
  cursor: pointer;
  color: var(--text-dim);
}
.shot-mode-toggle .mode-btn.active {
  background: var(--red);
  color: #fff;
}
.shot-mode-toggle .mode-btn[data-mode="goal"].active { background: var(--green); }
.shot-period { display: inline-flex; align-items: center; gap: 6px; font-size: 12px; }
.shot-period select { padding: 4px 6px; }
.shot-counts {
  display: inline-flex; gap: 14px; margin-left: auto;
  font-size: 13px;
}
.shot-counts .count b { font-size: 16px; color: var(--text); margin-right: 4px; }
.shot-counts .period-scope { color: var(--text-dim); font-weight: 700; }
/* Tap-a-dot action menu in the shot tracker — flat card, thumb-sized rows. */
/* Flat period-lock button — SVG padlock, brand color when engaged. */
#shot-lock-period { display: inline-flex; align-items: center; justify-content: center; }
#shot-lock-period .lock-svg { width: 17px; height: 17px; color: var(--text-dim); }
#shot-lock-period .lock-svg[hidden] { display: none; }
#shot-lock-period.is-locked .lock-svg { color: var(--brand-primary, var(--red)); }
/* ---------- Live tab, two-strip layout ---------- */
.gc-live-banner { margin-bottom: 10px; }
/* Ice-blue wash both ends — the brand-red tint read as pink here. Doubled
   selector outguns the later .gc-header-rich background. */
.gc-header-rich.gc-live-banner {
  background:
    linear-gradient(135deg, color-mix(in srgb, var(--sched-ice, #2864c8) 12%, transparent), transparent 55%),
    linear-gradient(225deg, color-mix(in srgb, var(--sched-ice, #2864c8) 12%, transparent), transparent 55%),
    #fff;
}
.gc-live-clockbox { display: flex; flex-direction: column; align-items: center; gap: 2px; }
.gc-live-clockbox .gc-clock-time {
  font-size: 36px; min-width: 0; padding: 0 10px; line-height: 1.1;
  font-family: 'Orbitron', 'Geist', system-ui, sans-serif;
  font-weight: 700;
  letter-spacing: 1px;
}
.gc-live-clockbox .gc-clock-period { font-size: 11px; font-weight: 800; text-transform: uppercase; letter-spacing: .4px; color: var(--text-dim); }
.gc-live-clock-controls { display: flex; align-items: center; gap: 6px; margin-top: 4px; flex-wrap: wrap; justify-content: center; }
.gc-live-clock-controls .btn { padding: 4px 12px; font-size: 12px; }
.gc-live-clock-controls .shot-goalie-select { width: auto; padding: 4px 6px; font-size: 12px; }
.gc-goalie-chip { font-size: 12px; color: var(--text-dim); }
.gc-goalie-chip b { color: var(--text); }
@media (max-width: 760px) {
  .gc-live-banner { flex-wrap: wrap; justify-content: center; row-gap: 10px; }
  .gc-live-banner .gc-divider { order: 3; flex-basis: 100%; }
}

.gc-topbar-title { font-size: 15px; font-weight: 700; min-width: 0; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.gc-game-strip {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px 22px;
  flex-wrap: wrap;
  margin-bottom: 10px;
}
.gc-strip-score { display: flex; flex-direction: column; gap: 4px; }
.gc-strip-score .shot-counts { margin-left: 0; font-size: 12px; gap: 10px; flex-wrap: wrap; }
.gc-strip-score .shot-counts .count b { font-size: 13px; }
.gc-track-strip {
  display: flex;
  align-items: center;
  gap: 8px 14px;
  flex-wrap: wrap;
  padding: 8px 12px;
  background: var(--bg-soft);
  border-radius: 6px;
  margin-bottom: 12px;
}
.gc-strip-divider { width: 1px; align-self: stretch; background: var(--border-soft); }
#shot-dot-menu[hidden] { display: none; }
#shot-dot-menu {
  position: absolute;
  z-index: 40;
  min-width: 190px;
  background: #fff;
  border: 1px solid var(--border-soft, #e6e8eb);
  border-radius: 10px;
  box-shadow: 0 8px 28px rgba(15, 23, 42, .18);
  padding: 6px;
  display: flex;
  flex-direction: column;
  gap: 2px;
}
#shot-dot-menu .sdm-head {
  font-size: 12px;
  font-weight: 700;
  color: var(--text-dim);
  padding: 6px 10px 8px;
  border-bottom: 1px solid var(--border-soft, #e6e8eb);
  margin-bottom: 4px;
  white-space: nowrap;
}
#shot-dot-menu button {
  appearance: none;
  border: 0;
  background: transparent;
  text-align: left;
  font: inherit;
  font-size: 14px;
  padding: 10px 10px;
  border-radius: 6px;
  cursor: pointer;
}
#shot-dot-menu button:hover { background: var(--bg-soft, #f4f5f7); }
#shot-dot-menu .sdm-danger { color: var(--danger, #dc2626); font-weight: 600; }

.shot-counts .goals b { color: var(--green); }
.shot-modal-body {
  display: grid;
  grid-template-columns: 1fr 240px;
  gap: 14px;
  min-height: 0;
  flex: 1;
}
.shot-rink-wrap { display: flex; flex-direction: column; min-width: 0; }
.shot-rink-stage {
  position: relative;
  /* Same surface artwork as the drill board — the SVG scales crisply. */
  background: #fff url('/assets/img/rink-full.svg?v=2') center / 100% 100% no-repeat;
  border: 1px solid var(--border-soft);
  border-radius: 8px;
  overflow: hidden;
  cursor: crosshair;
}
.shot-rink-stage canvas {
  position: absolute; inset: 0;
  width: 100%; height: 100%;
  display: block;
}
.shot-rink-stage canvas#shot-overlay { z-index: 2; }
.shot-hint {
  font-size: 12px; color: var(--text-dim);
  margin-top: 8px;
}
.shot-players {
  display: flex; flex-direction: column;
  min-height: 0;
  border: 1px solid var(--border-soft);
  border-radius: 8px;
  overflow: hidden;
}
.shot-players-head {
  background: var(--panel-dark);
  color: #fff;
  padding: 10px 14px;
  font-size: 12px;
  font-weight: 700;
  letter-spacing: 1px;
  text-transform: uppercase;
}
.shot-players-help {
  border-top: 1px solid var(--border-soft);
  padding: 8px 12px;
  font-size: 11px;
  color: var(--text-dim);
}
#shot-player-list { flex: 1; overflow-y: auto; }
.shot-player {
  display: flex; align-items: center; gap: 10px;
  width: 100%;
  background: #fff;
  border: none;
  border-bottom: 1px solid var(--border-soft);
  padding: 8px 12px;
  font-size: 13px;
  cursor: pointer;
  text-align: left;
}
.shot-player:hover { background: var(--bg-soft); }
.shot-player.active {
  background: var(--red);
  color: #fff;
}
.shot-player.active .pos { color: rgba(255,255,255,.8); }
.shot-player .num {
  display: inline-grid; place-items: center;
  width: 26px; height: 26px;
  border-radius: 50%;
  background: var(--bg-soft);
  color: var(--text);
  font-weight: 700;
  font-size: 12px;
  flex-shrink: 0;
}
.shot-player.active .num { background: #fff; color: var(--red); }
.shot-player .nm { flex: 1; font-weight: 500; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.shot-player .pos {
  font-size: 11px;
  color: var(--text-dim);
}

/* Shot tracker — Us/Them, scoreboard */
.shot-scoreboard {
  display: inline-flex; align-items: center; gap: 12px;
  background: var(--panel-dark);
  color: #fff;
  padding: 8px 16px;
  border-radius: 8px;
  margin-left: auto;
}
.shot-scoreboard .side { display: flex; flex-direction: column; align-items: center; }
.shot-scoreboard .lbl {
  font-size: 10px; text-transform: uppercase; letter-spacing: 1px;
  color: rgba(255,255,255,.7);
}
.shot-scoreboard .num { font-size: 26px; font-weight: 700; line-height: 1; }
.shot-scoreboard .vs { font-size: 22px; color: rgba(255,255,255,.4); }

.shot-period-tabs {
  display: inline-flex;
  background: #fff;
  border: 1px solid var(--border);
  border-radius: 20px;
  padding: 2px;
}
.shot-period-tabs .period-btn {
  background: transparent;
  border: none;
  padding: 6px 14px;
  border-radius: 16px;
  font-size: 13px;
  font-weight: 600;
  cursor: pointer;
  color: #5b6068;
}
.shot-period-tabs .period-btn:hover { color: #111; }
.shot-period-tabs .period-btn.active {
  background: var(--red, #7c5cff);
  color: #fff;
}
/* All shot-tracker toolbar controls share the same 32px height so they
   sit on a clean baseline regardless of which has labels / icons / text. */
.shot-modal-toolbar > * { height: 32px; box-sizing: border-box; }
.shot-modal-toolbar .shot-counts { height: auto; }

/* "We attack" group: inline label + arrow toggle, all at 32px. */
.shot-attack-group { display: inline-flex; align-items: center; gap: 6px; }
.shot-attack-label {
  font-size: 11px; font-weight: 600;
  color: var(--text-dim, #5b6068);
  text-transform: uppercase; letter-spacing: 0.4px;
  white-space: nowrap;
}
.shot-attack-toggle {
  display: inline-flex;
  background: #fff;
  border: 1px solid var(--border, #d4d7dc);
  border-radius: 16px;
  padding: 2px;
  align-items: center;
}
.shot-attack-toggle .attack-btn {
  background: transparent; border: none;
  padding: 0 12px;
  height: 24px;
  border-radius: 12px;
  font-size: 14px; font-weight: 700; line-height: 1;
  cursor: pointer; color: #5b6068;
}
.shot-attack-toggle .attack-btn.active { background: var(--red, #7c5cff); color: #fff; }

/* Plain icon — no border or background, just the glyph + tooltip. */
.shot-modal-toolbar .icon-btn-plain {
  display: inline-flex; align-items: center; justify-content: center;
  width: 32px; height: 32px;
  border: none;
  background: transparent;
  font-size: 18px; line-height: 1;
  cursor: pointer; color: #5b6068;
  padding: 0;
}
.shot-modal-toolbar .icon-btn-plain:hover { color: #111; }
.shot-modal-toolbar .icon-btn-plain:disabled { opacity: 0.35; cursor: not-allowed; }
#shot-lock-period.is-locked { color: var(--red, #7c5cff); }
/* Locked period tabs get a thin ring so the lock state is glanceable. */
.shot-period-tabs .period-btn.is-locked { box-shadow: inset 0 0 0 2px var(--red, #7c5cff); }
.shot-period-tabs .period-btn.is-locked::after {
  content: "";
  display: inline-block;
  width: 10px; height: 10px;
  margin-left: 5px;
  vertical-align: -1px;
  background: currentColor;
  -webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='3' stroke-linecap='round' stroke-linejoin='round'%3E%3Crect x='4' y='11' width='16' height='10' rx='2'/%3E%3Cpath d='M8 11V7a4 4 0 0 1 8 0v4'/%3E%3C/svg%3E") center / contain no-repeat;
  mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='3' stroke-linecap='round' stroke-linejoin='round'%3E%3Crect x='4' y='11' width='16' height='10' rx='2'/%3E%3Cpath d='M8 11V7a4 4 0 0 1 8 0v4'/%3E%3C/svg%3E") center / contain no-repeat;
}
/* When the active period is locked, dim & block the rink stage so the user
   can't even attempt a tap. The toolbar still works so the period can be
   unlocked. */
/* ---------- Unified Game Center: tabs + live event bar + extras ---------- */
/* Live | Summary pills — same pill language as the period / shot / attack
   toggles (white track, 20px radius, red active pill). */
.gc-tabs {
  display: inline-flex;
  background: #fff;
  border: 1px solid var(--border);
  border-radius: 20px;
  padding: 2px;
}
.gc-tab {
  appearance: none; border: 0; background: transparent;
  font: inherit; font-size: 13px; font-weight: 600;
  padding: 6px 16px; border-radius: 16px; cursor: pointer;
  color: #5b6068;
}
.gc-tab:hover { color: #111; }
.gc-tab.active { background: var(--brand-primary, var(--red)); color: #fff; }
.gc-pane { padding: 10px 16px 16px; }
#gc-summary-pane { padding: 0; }
.gc-event-bar {
  display: flex; align-items: center; gap: 12px; flex-wrap: wrap;
  padding: 8px 12px; margin-bottom: 12px;
  background: var(--bg-soft); border-radius: 6px;
  font-size: 13px;
}
.gc-event-btn { padding: 5px 12px; font-size: 13px; }
.gc-fo-group { display: inline-flex; align-items: center; gap: 6px; }
.gc-fo-label { color: var(--text-dim); font-weight: 700; font-size: 12px; text-transform: uppercase; letter-spacing: .3px; }
.gc-fo-tally { font-weight: 700; font-variant-numeric: tabular-nums; }
.gc-pen-strip { display: inline-flex; gap: 6px; flex-wrap: wrap; }
.gc-pen-chip {
  display: inline-flex; align-items: center; gap: 6px;
  background: #fff; border: 1px solid var(--border-soft);
  border-radius: 999px; padding: 3px 6px 3px 10px; font-size: 12px; font-weight: 600;
}
.gc-pen-chip.opp { border-color: color-mix(in srgb, var(--red) 40%, transparent); }
.gc-pen-x {
  appearance: none; border: 0; background: transparent; cursor: pointer;
  color: var(--text-dim); font-size: 14px; line-height: 1; padding: 2px 4px;
}
.gc-pen-x:hover { color: var(--red); }
.gc-extras-row { display: flex; gap: 12px; flex-wrap: wrap; margin-bottom: 12px; }
.gc-extra-card {
  border: 1px solid var(--border-soft); border-radius: 10px;
  padding: 12px 18px; min-width: 120px; background: #fff;
}
.gc-extra-num { font-size: 22px; font-weight: 800; font-variant-numeric: tabular-nums; }
.gc-extra-lbl { font-size: 12px; color: var(--text-dim); font-weight: 600; margin-top: 2px; }
.gc-pen-log { display: flex; flex-direction: column; gap: 4px; }
.gc-pen-row {
  display: flex; gap: 12px; align-items: baseline;
  font-size: 13px; padding: 6px 10px;
  border-left: 3px solid var(--border-soft); background: var(--bg-soft);
  border-radius: 0 6px 6px 0;
}
.gc-pen-row.opp { border-left-color: color-mix(in srgb, var(--red) 45%, transparent); }
.gc-pen-period { color: var(--text-dim); font-variant-numeric: tabular-nums; min-width: 82px; }
.gc-pen-who { font-weight: 700; }
.gc-pen-what { color: var(--text-dim); }
.gc-period-table {
  width: auto;
  border-collapse: collapse;
  margin-top: 14px;
  font-size: 13px;
  font-variant-numeric: tabular-nums;
}
.gc-period-table th, .gc-period-table td {
  padding: 6px 14px;
  text-align: center;
  border-bottom: 1px solid var(--border-soft);
}
.gc-period-table th { font-size: 11px; font-weight: 700; color: var(--text-dim); text-transform: uppercase; letter-spacing: .3px; }
.gc-period-table td:first-child, .gc-period-table th:first-child { text-align: left; font-weight: 600; }
.gc-period-goals { color: var(--text-dim); }
.gc-period-note { font-size: 11px; color: var(--text-dim); margin-top: 6px; }
.gc-shotmap-wrap { border: 1px solid var(--border-soft); border-radius: 10px; overflow: hidden; background: #fff; }
.gc-shotmap-wrap canvas { display: block; width: 100%; }
.gc-shotmap-legend { display: flex; gap: 16px; flex-wrap: wrap; font-size: 12px; color: var(--text-dim); margin-top: 8px; }
.gc-shotmap-legend .gc-dot { display: inline-block; width: 10px; height: 10px; border-radius: 50%; margin-right: 4px; vertical-align: -1px; }
.gc-dot-us { background: rgba(124, 92, 255,.88); }
.gc-dot-opp { background: rgba(100,116,139,.8); }
.gc-dot-goal { box-shadow: 0 0 0 2px #16a34a; }
.gc-fo-leaders { display: flex; gap: 14px; flex-wrap: wrap; font-size: 13px; margin-bottom: 12px; }
.gc-fo-leader b { font-variant-numeric: tabular-nums; }
@media (max-width: 700px) {
  .gc-topbar { grid-template-columns: 1fr; gap: 8px; justify-items: center; }
  .gc-topbar > div:last-child { justify-self: center; }
}

.shot-rink-stage.is-locked { opacity: 0.55; pointer-events: none; }

/* Phone: stack the shot tracker — full-width rink on top, wrapping toolbar,
   shooter list in a capped scroll region below. The rink canvas re-sizes
   from stage width, so stacking gives it the whole screen instead of a
   sliver beside the shooter column. */
@media (max-width: 700px) {
  .shot-modal-body { display: flex; flex-direction: column; }
  .shot-rink-wrap { order: 1; }
  .shot-players { order: 2; max-height: 260px; }
  /* flex:1 collapses to zero height once the column stops stretching —
     give the list a real floor so shooters stay tappable. */
  #shot-player-list { min-height: 140px; }
  .shot-modal-toolbar {
    flex-wrap: wrap;
    gap: 8px 14px;
  }
  .shot-counts {
    margin-left: 0;
    flex-wrap: wrap;
    gap: 8px 14px;
  }
}

/* ============================================================
   Schedule: view-mode toggle + calendar grid
   ============================================================ */
.schedule-view-toggle {
  display: inline-flex;
  background: #fff;
  border: 1px solid var(--border, #d4d7dc);
  border-radius: 16px;
  padding: 2px;
}
.schedule-view-toggle .view-tab {
  background: transparent; border: none;
  padding: 5px 12px;
  border-radius: 12px;
  font-size: 12px; font-weight: 600;
  cursor: pointer; color: #5b6068;
  line-height: 1;
}
.schedule-view-toggle .view-tab:hover { color: #111; }
.schedule-view-toggle .view-tab.active { background: var(--red, #7c5cff); color: #fff; }

.calendar-toolbar {
  display: flex; align-items: center; gap: 8px;
  padding: 10px 4px;
}
.calendar-toolbar .cal-title {
  font-size: 16px; font-weight: 700; margin-left: 6px;
}
.calendar-toolbar .cal-nav { padding: 4px 10px; font-size: 14px; }

.calendar-grid { border-top: 1px solid var(--border, #d4d7dc); }
.cal-row.cal-head {
  display: grid; grid-template-columns: repeat(7, 1fr);
  background: #fafafa;
  border-bottom: 1px solid var(--border, #d4d7dc);
}
.cal-dow {
  padding: 6px 8px;
  font-size: 11px; font-weight: 700;
  text-transform: uppercase; letter-spacing: 0.5px;
  color: var(--text-dim, #5b6068);
  text-align: left;
}
.cal-row.cal-body {
  display: grid; grid-template-columns: repeat(7, 1fr);
  grid-auto-rows: minmax(100px, auto);
}
.cal-cell {
  border-right: 1px solid var(--border, #d4d7dc);
  border-bottom: 1px solid var(--border, #d4d7dc);
  padding: 4px 6px 6px 6px;
  min-height: 100px;
  background: #fff;
  display: flex; flex-direction: column; gap: 4px;
  overflow: hidden;
}
.cal-cell:nth-child(7n) { border-right: none; }
.cal-cell.out { background: #fafafa; color: #b3b6bb; }
.cal-cell.today .cal-day-num {
  background: var(--red, #7c5cff); color: #fff;
  border-radius: 999px;
  width: 22px; height: 22px;
  display: inline-flex; align-items: center; justify-content: center;
}
.cal-day-num {
  font-size: 12px; font-weight: 600;
  color: #111;
  align-self: flex-start;
}
.cal-cell.out .cal-day-num { color: #b3b6bb; }
.cal-entries { display: flex; flex-direction: column; gap: 3px; }
.cal-entry {
  display: flex; align-items: center; gap: 4px;
  text-align: left;
  background: #f1f3f6;
  border: 1px solid transparent;
  border-left: 3px solid #5b6068;
  border-radius: 4px;
  padding: 2px 6px;
  font-size: 11px;
  line-height: 1.3;
  cursor: pointer;
  color: #1f2227;
  width: 100%;
  white-space: nowrap;
  overflow: hidden;
}
.cal-entry:hover { background: #e7eaef; }
.cal-entry.type-game     { border-left-color: var(--red, #7c5cff); }
.cal-entry.type-practice { border-left-color: #2563eb; }
.cal-entry.type-event    { border-left-color: #16a34a; }
.cal-entry-icon { flex: 0 0 auto; }
.cal-entry-time { flex: 0 0 auto; font-weight: 700; }
.cal-entry-text { flex: 1 1 auto; overflow: hidden; text-overflow: ellipsis; }
@media (max-width: 720px) {
  .cal-row.cal-body { grid-auto-rows: minmax(70px, auto); }
  .cal-cell { min-height: 70px; padding: 3px 4px; }
  .cal-entry-text { display: none; }
}

/* ============================================================
   Day view — single date, entries stacked + sorted by time
   ============================================================ */
.cal-day {
  border-top: 1px solid var(--border, #d4d7dc);
  padding: 20px;
  background: #fff;
}
.cal-day-list {
  display: flex;
  flex-direction: column;
  gap: 8px;
  max-width: 720px;
  margin: 0 auto;
}
.cal-day-list .cal-entry {
  font-size: 14px;
  padding: 10px 14px;
  gap: 10px;
}
.cal-day-empty {
  text-align: center;
  padding: 60px 20px;
  color: var(--text-dim);
  font-size: 14px;
}

/* ============================================================
   Week view — 7 columns side by side, entries vertically stacked
   ============================================================ */
.cal-week {
  display: grid;
  grid-template-columns: repeat(7, minmax(0, 1fr));
  border-top: 1px solid var(--border, #d4d7dc);
  border-left: 1px solid var(--border, #d4d7dc);
}
.cal-week-col {
  border-right: 1px solid var(--border, #d4d7dc);
  border-bottom: 1px solid var(--border, #d4d7dc);
  min-height: 280px;
  background: #fff;
  display: flex;
  flex-direction: column;
}
.cal-week-col.today { background: #fff7e6; }
.cal-week-col-head {
  padding: 8px 10px;
  border-bottom: 1px solid var(--border-soft, #e9ebef);
  background: #f7f8fa;
  position: sticky; top: 0;
  z-index: 1;
}
.cal-week-col.today .cal-week-col-head { background: #fef3c7; }
.cal-week-dow {
  font-size: 11px;
  text-transform: uppercase;
  letter-spacing: 0.6px;
  color: var(--text-dim);
  font-weight: 700;
}
.cal-week-num {
  font-size: 18px;
  font-weight: 700;
  color: var(--text);
  margin-top: 2px;
}
.cal-week-entries {
  padding: 6px 6px;
  display: flex;
  flex-direction: column;
  gap: 4px;
  flex: 1;
}
.cal-week-empty {
  color: #d4d7dc;
  text-align: center;
  font-size: 14px;
  padding: 8px 0;
}
@media (max-width: 720px) {
  .cal-week {
    grid-template-columns: 1fr;
  }
  .cal-week-col { min-height: 0; }
  .cal-week-col-head { display: flex; align-items: baseline; gap: 8px; }
  .cal-week-num { margin-top: 0; font-size: 15px; }
}

/* ============================================================
   Year view — 12 mini month grids in a 4×3 (or 3×4) layout
   ============================================================ */
.cal-year {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: 18px;
  padding: 20px;
  background: #fff;
  border-top: 1px solid var(--border, #d4d7dc);
}
@media (max-width: 1200px) { .cal-year { grid-template-columns: repeat(3, minmax(0,1fr)); } }
@media (max-width: 880px)  { .cal-year { grid-template-columns: repeat(2, minmax(0,1fr)); } }
@media (max-width: 540px)  { .cal-year { grid-template-columns: 1fr; } }
.cal-yr-month {
  font-size: 11px;
}
.cal-yr-month-head {
  font-size: 13px;
  font-weight: 700;
  margin-bottom: 6px;
  color: var(--text);
}
.cal-yr-dow {
  display: grid;
  grid-template-columns: repeat(7, 1fr);
  text-align: center;
  font-size: 10px;
  color: var(--text-dim);
  letter-spacing: 0.4px;
}
.cal-yr-grid {
  display: grid;
  grid-template-columns: repeat(7, 1fr);
  gap: 2px;
  margin-top: 2px;
}
.cal-yr-cell {
  aspect-ratio: 1;
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: 4px;
  background: #f5f6f7;
  position: relative;
  cursor: pointer;
  transition: background 120ms ease-out, transform 100ms ease-out;
}
.cal-yr-cell:active:not(.blank) { transform: scale(0.94); }
.cal-yr-cell.blank { background: transparent; cursor: default; }
.cal-yr-cell.today { outline: 2px solid var(--brand-secondary, #1f5fff); outline-offset: -2px; }
.cal-yr-cell.has-entries { color: white; font-weight: 700; }
.cal-yr-cell.has-game     { background: var(--red, #7c5cff); }
.cal-yr-cell.has-practice { background: #2563eb; }
.cal-yr-cell.has-event    { background: #16a34a; }
/* Multi-type day: blend via diagonal */
.cal-yr-cell.has-game.has-practice {
  background: linear-gradient(135deg, var(--red, #7c5cff) 50%, #2563eb 50%);
}
.cal-yr-cell.has-game.has-event {
  background: linear-gradient(135deg, var(--red, #7c5cff) 50%, #16a34a 50%);
}
.cal-yr-cell.has-practice.has-event {
  background: linear-gradient(135deg, #2563eb 50%, #16a34a 50%);
}
.cal-yr-num {
  font-size: 10px;
  line-height: 1;
}

/* ============================================================
   Custom date range — from/to pickers + filtered list
   ============================================================ */
.cal-range-toolbar {
  display: flex;
  align-items: center;
  gap: 16px;
  padding: 12px 14px;
  background: #f7f8fa;
  border-top: 1px solid var(--border, #d4d7dc);
}
.cal-range-input {
  display: flex;
  align-items: center;
  gap: 8px;
}
.cal-range-input label {
  font-size: 12px;
  text-transform: uppercase;
  letter-spacing: 0.5px;
  color: var(--text-dim);
  font-weight: 700;
}
.cal-range-input input[type="date"] {
  font: inherit;
  font-size: 14px;
  padding: 6px 10px;
  border: 1px solid var(--border, #d4d7dc);
  border-radius: 6px;
  background: white;
}
.cal-range-count {
  margin-left: auto;
  font-size: 13px;
  color: var(--text-dim);
  font-weight: 500;
}
.cal-range-list {
  display: flex;
  flex-direction: column;
  background: #fff;
}
.cal-range-row {
  display: grid;
  grid-template-columns: 130px 90px 28px 1fr;
  align-items: center;
  gap: 12px;
  padding: 12px 16px;
  background: transparent;
  border: none;
  border-bottom: 1px solid var(--border-soft, #e9ebef);
  font: inherit;
  text-align: left;
  cursor: pointer;
  transition: background 140ms ease-out, transform 120ms ease-out;
}
.cal-range-row:hover { background: #f5f6f7; }
.cal-range-row:active { transform: scale(0.99); }
.cal-range-row:last-child { border-bottom: none; }
.cal-range-date { font-weight: 600; font-size: 13px; }
.cal-range-time { font-weight: 700; color: var(--text-dim); font-size: 13px; }
.cal-range-icon { display: flex; align-items: center; justify-content: center; }
.cal-range-text { font-size: 14px; }
.cal-range-row.type-game     .cal-range-icon { color: var(--red, #7c5cff); }
.cal-range-row.type-practice .cal-range-icon { color: #2563eb; }
.cal-range-row.type-event    .cal-range-icon { color: #16a34a; }
@media (max-width: 540px) {
  .cal-range-toolbar { flex-wrap: wrap; gap: 10px; }
  .cal-range-row {
    grid-template-columns: 1fr auto;
    grid-template-rows: auto auto;
    gap: 4px 10px;
  }
  .cal-range-date { grid-column: 1; grid-row: 1; }
  .cal-range-time { grid-column: 2; grid-row: 1; text-align: right; }
  .cal-range-icon { grid-column: 1; grid-row: 2; }
  .cal-range-text { grid-column: 2; grid-row: 2; }
}

/* ID selector to beat the generic `.modal select` rule (which sets width:100%
   + padding:10px 12px and would otherwise clip the text vertically and make
   the dropdown stretch across the toolbar). */
#shot-goalie-select {
  padding: 5px 12px;
  border: 1px solid var(--border, #d4d7dc);
  border-radius: 6px;
  font-size: 13px;
  background: #fff;
  width: auto;
  min-width: 170px;
}

.shot-side-toggle {
  display: inline-flex;
  background: #fff;
  border: 1px solid var(--border);
  border-radius: 20px;
  padding: 2px;
}
.shot-side-toggle .side-btn {
  background: transparent;
  border: none;
  padding: 6px 14px;
  border-radius: 16px;
  font-size: 13px;
  font-weight: 500;
  cursor: pointer;
  color: var(--text-dim);
}
.shot-side-toggle .side-btn.active {
  background: var(--blue);
  color: #fff;
}
.shot-counts .them {
  color: var(--text-dim);
}

#shot-player-list.disabled {
  pointer-events: none;
  opacity: .35;
  position: relative;
}
#shot-player-list.disabled::after {
  content: 'Switch to Our Team to pick a shooter';
  position: absolute; inset: 0;
  display: grid; place-items: center;
  color: var(--text-dim);
  font-size: 12px;
  padding: 12px;
  text-align: center;
  pointer-events: auto;
}

/* ============================================================
   COLLAPSIBLE LEFT TOOLBAR + RIGHT SIDEBAR
   ============================================================ */
.collapse-btn {
  background: transparent;
  border: 1px solid rgba(255,255,255,.25);
  color: rgba(255,255,255,.85);
  width: 22px; height: 22px;
  border-radius: 4px;
  cursor: pointer;
  font-size: 14px;
  line-height: 1;
  padding: 0;
  display: inline-grid;
  place-items: center;
  margin-left: auto;
}
.toolbar-header { display: flex; align-items: center; gap: 8px; }
.toolbar-header .collapse-btn { margin-left: auto; }
.sidebar-tabs { position: relative; }
.sidebar-tabs .collapse-btn.right {
  position: absolute; right: 6px; top: 50%; transform: translateY(-50%);
}
.collapse-btn:hover { background: rgba(255,255,255,.12); color: #fff; }

/* Re-expand strips — narrow vertical bars shown when their panel is collapsed */
.collapse-strip {
  display: none;
  width: 22px;
  background: var(--panel-dark);
  color: #fff;
  border: none;
  cursor: pointer;
  font-size: 18px;
  font-weight: 700;
  padding: 0;
  align-self: stretch;
  border-left: 1px solid #1a1d22;
  border-right: 1px solid #1a1d22;
}
.collapse-strip:hover { background: var(--panel-accent); }

/* When collapsed, the toolbar / sidebar disappear and the strip takes their column. */
body.route-drill .app main { transition: grid-template-columns .15s ease; }
body.tools-collapsed .app main {
  grid-template-columns: 22px minmax(0, 1fr) 300px;
}
body.sidebar-collapsed .app main {
  grid-template-columns: 108px minmax(0, 1fr) 22px;
}
body.tools-collapsed.sidebar-collapsed .app main {
  grid-template-columns: 22px minmax(0, 1fr) 22px;
}
body.tools-collapsed   .toolbar { display: none; }
body.tools-collapsed   .collapse-strip.left  { display: block; }
body.sidebar-collapsed .sidebar { display: none; }
body.sidebar-collapsed .collapse-strip.right { display: block; }

/* Drag-and-drop drill cards from the sidebar onto the rink to load them
   into the current tab. The card is the drag source; the IMG inside is
   non-draggable so the browser doesn't initiate an image-drag instead. */
.drill-card[draggable="true"] { cursor: grab; }
.drill-card[draggable="true"]:active { cursor: grabbing; }
.drill-card .thumb {
  -webkit-user-drag: none;
  user-select: none;
  pointer-events: none;
}
.drop-target {
  outline: 3px dashed var(--brand-primary, #2864c8);
  outline-offset: -6px;
  background: rgba(40, 100, 200, 0.06);
}

/* Tablet-range responsive tweak — slightly tightens the side columns.
 * Scoped to MIN-width 769px so it doesn't override the mobile drill
 * layout (the mobile rule lives in the max-width:768px block below and
 * has lower specificity than this one's :not()-chain). Also uses
 * minmax(0, 1fr) so the middle column can shrink below its content's
 * intrinsic min-content size — without this, a wide rink in the
 * canvas-frame would blow the column out past the viewport. */
@media (min-width: 769px) and (max-width: 1100px) {
  body:not(.tools-collapsed):not(.sidebar-collapsed) .app main {
    grid-template-columns: 96px minmax(0, 1fr) 260px;
  }
}

/* ============================================================
   ROTATED RINK (portrait / narrow viewports)
   ============================================================
   When the frame rotates into portrait mode, EVERY child rotates as
   one unit: the rink IMG, the team-logo IMG, and both canvases. If
   the canvases stay landscape while the IMG rotates, the canvas's
   landscape pixel buffer gets squashed into the portrait CSS box,
   producing stretched-looking strokes/stamps AND mismatched
   tap-to-canvas coordinates. width/height are set inline by fitCanvas
   to the pre-rotation (landscape) size for all four; CSS then rotates
   them -90° together so the rendered content keeps its aspect ratio
   and the canvas's design coords stay aligned with the IMG. */
.canvas-frame.rotated > #rink-image,
.canvas-frame.rotated > #rink-team-logo,
.canvas-frame.rotated > #rink,
.canvas-frame.rotated > #drawing {
  inset: auto !important;
  top: 50% !important;
  left: 50% !important;
  transform: translate(-50%, -50%) rotate(-90deg) !important;
  transform-origin: center center !important;
}

/* ============================================================
   ICON NORMALIZATION — crisper, consistent UI icons
   ============================================================ */
/* Rendering hints applied to all icon SVGs in the chrome. */
.tool svg,
.top-icon-btn svg,
.collapse-btn svg,
.rink-btn svg,
.topnav svg,
.user-menu svg,
.rink-menu svg,
.team-chip svg,
.team-menu svg,
.shot-modal-header svg,
.shot-modal-toolbar svg,
.modal-actions svg,
.plan-card svg,
.drill-card svg,
.player-card svg,
.category-item svg,
.acts svg,
.del svg,
.edit svg,
.rate svg,
.rm svg {
  shape-rendering: geometricPrecision;
  stroke-linecap: round;
  stroke-linejoin: round;
}

/* Standardise stroke weight on 24x24 line icons so the whole UI reads at one density.
   The line-style preview buttons (.lp-btn) keep their original strokes — they're
   miniature previews of the actual brush widths and need to vary. */
.tool svg[viewBox="0 0 24 24"],
.top-icon-btn svg[viewBox="0 0 24 24"],
.collapse-btn svg[viewBox="0 0 24 24"],
.rink-btn svg[viewBox="0 0 24 24"],
.user-menu svg[viewBox="0 0 24 24"],
.rink-menu svg[viewBox="0 0 24 24"],
.team-chip svg[viewBox="0 0 24 24"],
.team-menu svg[viewBox="0 0 24 24"],
.acts svg[viewBox="0 0 24 24"],
.plan-card svg[viewBox="0 0 24 24"],
.drill-card svg[viewBox="0 0 24 24"],
.player-card svg[viewBox="0 0 24 24"],
.category-item svg[viewBox="0 0 24 24"],
.del svg[viewBox="0 0 24 24"],
.edit svg[viewBox="0 0 24 24"],
.rate svg[viewBox="0 0 24 24"],
.rm svg[viewBox="0 0 24 24"] {
  stroke-width: 2;
}

/* Consistent display sizes */
.tool > svg          { width: 22px; height: 22px; display: block; }
.top-icon-btn > svg  { width: 20px; height: 20px; display: block; }
.collapse-btn svg    { width: 14px; height: 14px; }

/* Crisper text-bearing icons (R/H, V/H goalie stamps + jersey labels) */
.tool text { text-rendering: geometricPrecision; }
.player-label, .player-label .sub { -webkit-font-smoothing: antialiased; }

/* ============================================================
   iOS / TOUCH POLISH
   ============================================================ */
* {
  -webkit-tap-highlight-color: transparent;
}
button,
.tool,
.lp-btn,
.swatch,
.collapse-btn,
.collapse-strip,
.topnav-link,
.team-chip,
.sidebar-tab,
.shot-player,
.mode-btn,
.side-btn {
  -webkit-user-select: none;
  user-select: none;
  -webkit-touch-callout: none;
}
/* Drawing canvas should not bubble touch as scroll/zoom (we set this already
   for the drill canvas; also apply to overlay canvases used in modals). */
#shot-overlay, #shot-rink, #drawing, #rink {
  touch-action: none;
}

/* On touch-only devices iOS Safari "sticks" :hover after a tap, so a
 * button that briefly highlights stays in its hover background forever.
 * For our style-bar buttons that means a light-grey :hover bg keeps
 * showing even when the .active class never landed — easy to confuse
 * for "I selected this" when really the tap didn't register at all.
 * Disable the hover background entirely on hover-less devices so a tap
 * either flashes-then-clears (no selection) or shows the actual .active
 * red/blue treatment (selection took). */
@media (hover: none) {
  /* CRITICAL: scope to :not(.active) so the .active state's red
   * background isn't clobbered by this rule. Without :not(.active),
   * iPad shows .active buttons as flat-white because sticky :hover
   * + this transparent override wins over .active (same specificity,
   * later source order). */
  .tool:hover:not(.active),
  .lp-btn:hover:not(.active),
  .top-icon-btn:hover,
  .lp-swatches .swatch:hover:not(.active) { background: transparent; transform: none; }
  .tool:hover:not(.active) { border-color: var(--border-soft); }
}

/* iPad + smaller laptops: the bottom style bar (.line-picker) doesn't
 * fit all of style+ending+colour+size+pos-num in one horizontal row on
 * narrower viewports, and iOS users were asking why they had to swipe
 * horizontally to reach a swatch or position-number. Wrap to multiple
 * rows on screens narrower than typical desktop so everything is
 * tap-reachable without scrolling. The bar grows taller; canvas-stage
 * (flex:1 sibling) shrinks to absorb that and the canvas re-fits on
 * next resize via fitCanvas() in rink.js. 1366px breakpoint covers
 * every current iPad in both portrait and landscape. */
@media (max-width: 1366px) {
  .line-picker {
    flex-wrap: wrap;
    overflow-x: visible;
    row-gap: 4px;
    column-gap: 8px;
    padding: 4px 8px;
  }
  /* Vertical dividers look out-of-place once wrapping puts groups on
   * different rows — wrap itself separates groups visually. */
  .line-picker-divider { display: none; }
  /* Drop the STYLE / ENDING / COLOR / # / SIZE captions on tighter
   * viewports — the buttons themselves are recognizable enough and
   * the labels were eating ~20-30px per group. */
  .line-picker .lp-label { display: none; }
  .line-picker-group { gap: 4px; }
  /* Compact, squarish lp-btn so each group (line styles / endings /
   * pos-nums) fits its full set on a single sub-row. The internal
   * SVG/img line preview is shrunk to match — these are hint-icons,
   * not measurements. */
  .lp-btn {
    min-width: 32px;
    min-height: 32px;
    padding: 3px;
  }
  .lp-btn svg,
  .lp-btn img {
    width: 24px;
    height: 14px;
  }
  .lp-options { padding: 1px; gap: 1px; }
  /* Position-number badges keep their square aspect but get the
   * same tighter sizing as their lp-btn siblings. */
  .lp-btn.pos-num-btn { min-width: 32px; min-height: 32px; padding: 2px; }
  .lp-btn.pos-num-btn svg { width: 26px; height: 26px; }
  /* Swatches: shrink a touch and tighten the row gap to match. */
  .lp-swatches { gap: 3px; }
  .lp-swatches .swatch { width: 24px; height: 24px; }
}

/* iOS Safari 100vh fix. iOS computes vh from the *largest* viewport
 * (URL bar hidden), so any layout sized to 100vh while the URL bar
 * is visible has its bottom edge below the visible area. On iPad
 * landscape this was hiding the style bar even though the layout
 * thought it was on-screen. `dvh` (dynamic viewport height, iOS
 * 15.4+) updates as the chrome shows/hides, so 100dvh is always
 * what the user can actually see. @supports keeps older iOS on the
 * vh fallback. */
@supports (height: 100dvh) {
  body.route-drill .page-main {
    height: calc(100dvh - 52px - env(safe-area-inset-top));
  }
  body.route-drill:has(.billing-banner) .page-main {
    height: calc(100dvh - 88px - env(safe-area-inset-top));
  }
}

/* iPad: the desktop canvas-stage min-height (100vh - 220px) was sized for
 * a single-row line-picker. With the wrap-to-rows rule above the line-
 * picker is ~140-160px tall instead of ~50px, so the stage min-height
 * shoves the line-picker below the visible viewport. Lower the stage's
 * minimum on tablet-ish widths and use dvh so the calc is accurate to
 * what the user can actually see. Meta tags + notes still live below
 * the line-picker and remain reachable via canvas-wrap's overflow scroll.
 * In anim mode the anim-panel takes another ~140px, so shrink the stage
 * further so the timeline strip stays on-screen. */
@media (max-width: 1366px) {
  body.route-drill .canvas-stage {
    min-height: calc(100vh - 320px - var(--style-bar-extra, 0px));  /* fallback for pre-dvh iOS */
  }
  body.route-drill.anim-active .canvas-stage {
    min-height: calc(100vh - 460px - var(--style-bar-extra, 0px));
  }
}
@supports (height: 100dvh) {
  @media (max-width: 1366px) {
    body.route-drill .canvas-stage {
      min-height: calc(100dvh - 320px - var(--style-bar-extra, 0px));
    }
    body.route-drill.anim-active .canvas-stage {
      min-height: calc(100dvh - 460px - var(--style-bar-extra, 0px));
    }
  }
}

/* Safe-area insets — keep the top nav clear of the iPhone notch */
.topnav {
  padding-top:    env(safe-area-inset-top);
  padding-left:   max(16px, env(safe-area-inset-left));
  padding-right:  max(16px, env(safe-area-inset-right));
  height: calc(52px + env(safe-area-inset-top));
}
body.route-drill .page-main {
  height: calc(100vh - 52px - env(safe-area-inset-top));
}
.page-main {
  padding-bottom: env(safe-area-inset-bottom);
}

/* iOS auto-zooms on focus if input font-size < 16px. Pin to 16px on small screens. */
@media (max-width: 768px) {
  input[type="text"],
  input[type="number"],
  input[type="password"],
  input[type="date"],
  select,
  textarea {
    font-size: 16px !important;
  }
  /* Bigger tap targets on small screens (Apple HIG ≥ 44pt) */
  .tool { min-height: 48px; }
  .lp-btn { min-height: 36px; min-width: 50px; }
  .lp-swatches .swatch { width: 28px; height: 28px; }
  .top-icon-btn { padding: 10px; }
  .top-icon-btn svg { width: 22px; height: 22px; }
}

/* Modals: don't overflow narrow screens */
.modal {
  max-width: 96vw;
  max-height: 90vh;
  overflow: auto;
}

/* Top nav: let links scroll horizontally on narrow viewports instead of wrapping */
.topnav-links {
  -webkit-overflow-scrolling: touch;
  scrollbar-width: none;
}
.topnav-links::-webkit-scrollbar { display: none; }

/* ---------- Mobile hamburger + nav drawer ---------- */
/* Two staggered rounded lines — the short one stretches on press and the
 * pair morphs into an X while the drawer is open. */
.nav-hamburger {
  display: none;
  flex-direction: column;
  align-items: flex-end;
  justify-content: center;
  gap: 6px;
  width: 40px;
  height: 40px;
  background: transparent;
  border: 0;
  color: #fff;
  padding: 9px;
  cursor: pointer;
  border-radius: 10px;
  -webkit-tap-highlight-color: transparent;
}
.nav-hamburger:hover,
.nav-hamburger:active { background: rgba(255,255,255,.08); }
.nh-line {
  display: block;
  height: 2.5px;
  border-radius: 2px;
  background: currentColor;
  transition: width .22s cubic-bezier(.3,.9,.4,1.1), transform .22s cubic-bezier(.3,.9,.4,1.1);
}
.nh-line-1 { width: 22px; }
.nh-line-2 { width: 14px; }
.nav-hamburger:hover .nh-line-2,
.nav-hamburger:active .nh-line-2 { width: 22px; }
.nav-hamburger[aria-expanded="true"] .nh-line-1 { width: 22px; transform: translateY(4.25px) rotate(45deg); }
.nav-hamburger[aria-expanded="true"] .nh-line-2 { width: 22px; transform: translateY(-4.25px) rotate(-45deg); }

.nav-drawer-backdrop {
  display: none;
  position: fixed;
  inset: 0;
  background: rgba(0,0,0,.45);
  z-index: 89;
}
.nav-drawer {
  display: none;
  position: fixed;
  top: 0; right: 0; bottom: 0;
  width: min(300px, 86vw);
  background: var(--panel-dark);
  color: #fff;
  z-index: 90;
  flex-direction: column;
  padding: 14px 14px max(14px, env(safe-area-inset-bottom));
  box-shadow: -8px 0 28px rgba(0,0,0,.35);
  overflow-y: auto;
}
body.nav-drawer-open .nav-drawer { display: flex; }
body.nav-drawer-open .nav-drawer-backdrop { display: block; }
.nav-drawer-head {
  display: flex; align-items: center; justify-content: space-between;
  margin-bottom: 8px;
  font-size: 11px; font-weight: 700; letter-spacing: 1px;
  text-transform: uppercase; color: rgba(255,255,255,.55);
}
.nav-drawer-close {
  background: transparent; border: 0; color: #fff;
  padding: 6px; cursor: pointer; border-radius: 4px;
}
.nav-drawer-close:hover { background: rgba(255,255,255,.08); }
.nav-drawer-links { display: flex; flex-direction: column; gap: 2px; }
.nav-drawer-link {
  display: block;
  padding: 12px 12px;
  border-radius: 6px;
  color: #fff;
  font-size: 14px;
  font-weight: 500;
  text-decoration: none;
  background: transparent;
  border: 0;
  text-align: left;
  cursor: pointer;
  width: 100%;
}
.nav-drawer-link:hover { background: rgba(255,255,255,.08); }
.nav-drawer-link.active { background: var(--brand-primary); }
.nav-drawer-section {
  margin-top: 14px;
  padding-top: 14px;
  border-top: 1px solid rgba(255,255,255,.1);
}
.nav-drawer-label {
  font-size: 10px; font-weight: 700; letter-spacing: 1px;
  text-transform: uppercase; color: rgba(255,255,255,.45);
  margin-bottom: 6px;
}
.nav-drawer-team { font-size: 14px; font-weight: 500; padding: 4px 0; }
.nav-drawer-team-btn {
  display: block; width: 100%; text-align: left;
  background: rgba(255,255,255,.05); border: 1px solid rgba(255,255,255,.1);
  color: #fff;
  padding: 10px 12px;
  border-radius: 6px;
  font-size: 13px;
  cursor: pointer;
  margin-top: 4px;
}
.nav-drawer-team-btn:hover { background: rgba(255,255,255,.12); }
.nav-drawer-signout { color: #ff8a85; }

@media (max-width: 768px) {
  .topnav {
    gap: 8px;
    padding-left: max(10px, env(safe-area-inset-left));
    padding-right: max(10px, env(safe-area-inset-right));
  }
  .topnav .brand-text { display: none; }            /* keep the R mark, drop the word */
  .topnav-link { padding: 8px 10px; font-size: 12px; }
  .team-chip .team-name { max-width: 70px; }
  .logout-btn { padding: 6px 8px; font-size: 11px; }
  /* On mobile, swap the inline nav + chip/signout for a hamburger that opens
     the drawer above. Brand stays at the left. */
  .nav-hamburger { display: inline-flex; margin-left: auto; }
  .topnav-links,
  .topnav-right { display: none; }

  /* Mobile drill layout:
     - Toolbar stays visible (no auto-collapse), sized down a touch
     - Sidebar is removed from the grid and becomes a slide-in DRAWER overlay,
       defaults to closed (JS adds `sidebar-collapsed` on init).
     The right strip is the handle to slide it open. */
  body.route-drill .app main { position: relative; }
  /* Wider strip on mobile — 22px is below Apple's 44pt touch target and the
     rotated canvas overlaps it. Bump to 36px and give it a higher z-index
     so no canvas-rotation overflow can steal taps on the handle. */
  body.route-drill .app main,
  body.route-drill.sidebar-collapsed .app main {
    grid-template-columns: 88px minmax(0, 1fr) 36px;
  }
  body.route-drill.tools-collapsed .app main,
  body.route-drill.tools-collapsed.sidebar-collapsed .app main {
    grid-template-columns: 36px minmax(0, 1fr) 36px;
  }
  /* Sidebar = overlay drawer */
  body.route-drill .sidebar {
    position: absolute;
    top: 0; right: 0; bottom: 0;
    width: min(320px, 88vw);
    z-index: 50;
    box-shadow: -8px 0 28px rgba(0,0,0,.18);
    transform: translateX(0);
    transition: transform .25s ease;
    display: flex;          /* override default-flex-when-not-collapsed without touching .show class */
  }
  body.route-drill.sidebar-collapsed .sidebar {
    transform: translateX(100%);
    pointer-events: none;
  }
  /* Right strip is the "DRILLS" handle on mobile — only shown when the
     drawer is CLOSED (sidebar-collapsed). When the drawer is open, the
     drawer itself covers the strip, so we hide it to avoid the visual
     duplication and the dead tappable area behind the drawer.
     Explicit z-index + pointer-events so the rotated canvas (which can
     have overflow visible) can't sit on top of the handle. Stacks a
     vertical "DRILLS" label below the chevron so the handle is
     unmistakable — a bare 22px-wide strip with a `‹` is too easy to
     miss on a phone. */
  body.route-drill.sidebar-collapsed .collapse-strip.right {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 6px;
    z-index: 51;
    position: relative;
    pointer-events: auto;
    font-size: 20px;
    width: 100%;  /* fill the 36px grid column (override base .collapse-strip { width: 22px }) */
    background: var(--brand-primary, var(--panel-dark));
  }
  body.route-drill:not(.sidebar-collapsed) .collapse-strip.right {
    display: none;
  }
  body.route-drill.sidebar-collapsed .collapse-strip.right::after {
    content: 'DRILLS';
    writing-mode: vertical-rl;
    transform: rotate(180deg);
    letter-spacing: 0.18em;
    font-size: 11px;
    font-weight: 700;
    color: rgba(255, 255, 255, 0.95);
  }
  /* Left strip only shows when tools are explicitly collapsed (default = toolbar visible). */
  body.route-drill .collapse-strip.left { display: none; }
  body.route-drill.tools-collapsed .collapse-strip.left {
    display: block;
    z-index: 51;
    position: relative;
    pointer-events: auto;
    font-size: 22px;
    width: 100%;
  }
  body.route-drill.tools-collapsed .toolbar { display: none; }

  /* Tighter toolbar widths on mobile so the rink gets more room */
  .toolbar-header { padding: 6px 8px; font-size: 11px; }
  .tool-grid { padding: 3px; gap: 2px; }
  .tool { min-height: 40px; }     /* still tappable; HIG says ≥44pt but our buttons are dense */

  /* Backdrop behind the open drawer — tap outside the sidebar to close it. */
  body.route-drill:not(.sidebar-collapsed) .canvas-wrap::after {
    content: '';
    position: absolute;
    inset: 0;
    background: rgba(0,0,0,.18);
    z-index: 40;
    pointer-events: auto;
  }

  /* Plans/Evals/Roster/Games/Team pages: shrink the inner page padding */
  .page { padding: 16px 12px 40px; }
  .page-header { gap: 10px; }
  .page-header h1 { font-size: 18px; }

  /* Mobile drill page: let the page scroll vertically so the rink can take a
     bigger slice and the style bar / tags / notes flow underneath. */
  html, body { overflow-y: auto; }
  body.route-drill { height: auto; min-height: 100%; overflow: visible; } /* overflow:visible — the desktop rules hide body overflow; on the scrolling mobile layout that made body a (non-scrolling) scrollport and the sticky .topnav scrolled away with the page (iPad "top bar disappears") */
  body.route-drill .app { height: auto; min-height: 100vh; overflow-x: clip; overflow-y: visible; /* clip (not hidden): hidden makes .app a scroll container, which detaches the sticky .topnav from the real (html) scroller → top bar scrolled away on iPad portrait */ }
  /* The desktop drill layout caps .page-main to the viewport height (so the
     rink fits in one screen). On mobile we explicitly opt out — the content
     is taller than the viewport, and the user scrolls. */
  body.route-drill .page-main { height: auto; min-height: calc(100vh - 52px - env(safe-area-inset-top)); }
  body.route-drill .app main {
    overflow: visible;
    /* Give the rink ~85% of the viewport height so the style bar / meta / notes
       sit below the fold and scroll into view. */
    min-height: calc(100vh - 130px);
  }
  body.route-drill .canvas-wrap { overflow: visible; padding-bottom: 12px; }
  body.route-drill .canvas-stage { min-height: calc(100vh - 200px); }
  body.route-drill .toolbar { max-height: calc(100vh - 130px); overflow-y: auto; }
  /* On mobile the canvas needs full gesture control — pan-y was letting
     every vertical drawing motion become a page scroll, so users couldn't
     draw vertical lines or down-swiping strokes. The page is still
     scrollable: just touch the topbar, tab strip, style bar, notes, or
     drill sidebar above/below the canvas to scroll. */
  #drawing, #rink { touch-action: none; }
}

/* The very narrow phone / portrait orientation: stack the topbar on the drill page
   so it doesn't crowd out the rink. */
@media (max-width: 540px) {
  .topbar-center .drill-name { width: 100%; }
  .topbar-left { flex-shrink: 0; }
  .topbar { gap: 4px; padding: 6px 8px; }
}

/* ===================== AI result blocks (plan / suggest drills) ===================== */
.ai-result {
  margin: 12px 0;
  padding: 12px;
  border: 1px solid var(--border-soft);
  border-radius: 8px;
  background: #fafbfc;
  max-height: 50vh;
  overflow-y: auto;
  font-size: 13px;
}
.ai-result .ai-plan-name { font-size: 15px; margin-bottom: 4px; }
.ai-result .ai-plan-summary { font-style: italic; color: var(--text-dim); margin: 4px 0 8px; }
.ai-result ol.ai-plan-drills { margin: 8px 0 0 18px; padding: 0; }
.ai-result ol.ai-plan-drills > li { margin-bottom: 10px; }
.ai-result ul { margin: 4px 0 0 18px; color: var(--text-dim); font-size: 12px; }

/* ===================== Team profile page ===================== */
.page-team .page-header-actions { display: flex; gap: 8px; }
.page-team .field {
  display: flex; flex-direction: column; gap: 4px;
  font-size: 12px; color: var(--text-dim);
}
.page-team .field > span { font-weight: 500; }
.page-team .field input[type="text"],
.page-team .field input[type="email"],
.page-team .field input[type="tel"],
.page-team .field input[type="url"],
.page-team .field textarea {
  width: 100%; padding: 8px 10px;
  border: 1px solid var(--border-soft); border-radius: 6px;
  font-size: 14px; color: var(--text); background: #fff;
  font-family: inherit;
}
.page-team .field input:focus,
.page-team .field textarea:focus { outline: 2px solid var(--accent); outline-offset: -1px; }
.page-team .field-wide { grid-column: 1 / -1; }

/* ── Create-team wizard modal (global — opened from the team switcher) ── */
.create-team-modal { width: 560px; max-width: 94vw; max-height: 90vh; overflow-y: auto; }
.create-team-modal h3 { margin: 0 0 2px; }
.create-team-modal .modal-sub { margin: 0 0 16px; font: 400 13px/1.5 Geist, system-ui, sans-serif; color: var(--text-dim); }
.create-team-modal .field { display: flex; flex-direction: column; gap: 5px; font-size: 12px; color: var(--text-dim); margin-bottom: 12px; }
.create-team-modal .field > span { font-weight: 600; }
.create-team-modal .field input,
.create-team-modal .field select {
  width: 100%; padding: 9px 11px; border: 1px solid var(--border-soft, #e3e6ea); border-radius: 8px;
  font: 400 14px/1.3 Geist, system-ui, sans-serif; color: var(--text); background: #fff;
}
.create-team-modal .field input:focus,
.create-team-modal .field select:focus { outline: 2px solid var(--brand-primary, #7c5cff); outline-offset: -1px; border-color: transparent; }
.create-team-modal .ct-grid { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 0 14px; }
.create-team-modal .ct-wide { grid-column: 1 / -1; }
@media (max-width: 560px) { .create-team-modal .ct-grid { grid-template-columns: 1fr; } }

.profile-grid {
  display: grid; grid-template-columns: 200px 1fr; gap: 24px; align-items: start;
}
.profile-logo-block { display: flex; flex-direction: column; gap: 8px; }
.logo-preview {
  width: 180px; height: 180px;
  border-radius: 12px;
  border: 1px dashed var(--border-soft);
  background: var(--bg-soft) center/contain no-repeat;
  display: flex; align-items: center; justify-content: center;
  color: var(--text-dim); font-size: 13px;
}
.logo-placeholder { opacity: 0.6; }
.logo-actions { display: flex; gap: 6px; flex-wrap: wrap; }
.logo-actions .btn { cursor: pointer; }
.profile-logo-block .hint { font-size: 11px; color: var(--text-dim); }

.field-grid {
  display: grid; grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 12px;
}
.field-grid .color-row {
  display: flex; gap: 8px; align-items: center;
}
.field-grid .color-row input[type="color"] {
  width: 44px; height: 36px; padding: 2px; border: 1px solid var(--border-soft); border-radius: 6px; background: #fff;
}
.field-grid .color-row input[type="text"] { flex: 1; font-family: ui-monospace, Menlo, monospace; text-transform: uppercase; }

.social-grid {
  display: grid; grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 12px;
}

.coach-list { display: flex; flex-direction: column; gap: 12px; }
.coach-row {
  border: 1px solid var(--border-soft);
  border-radius: 8px;
  padding: 12px;
  background: #fcfcfd;
  display: flex; flex-direction: column; gap: 10px;
}
.coach-row-grid {
  display: grid; grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 10px;
}
.coach-row-actions { display: flex; justify-content: flex-end; }

.btn.btn-ghost {
  background: transparent; border-color: var(--border-soft); color: var(--text-dim);
}

.ai-key-row { display: flex; gap: 8px; align-items: center; flex-wrap: wrap; }
.ai-key-row input {
  flex: 1; min-width: 220px;
  padding: 8px 10px;
  border: 1px solid var(--border-soft); border-radius: 6px;
  font-family: ui-monospace, Menlo, monospace; font-size: 13px;
}

code.invite-code {
  font-family: ui-monospace, Menlo, monospace;
  padding: 4px 10px; background: var(--bg-soft); border-radius: 4px;
  font-size: 13px; letter-spacing: 1px;
}

@media (max-width: 768px) {
  .profile-grid { grid-template-columns: 1fr; }
  .logo-preview { width: 160px; height: 160px; }
  .field-grid, .social-grid, .coach-row-grid { grid-template-columns: 1fr; }
}

/* ============ Associations pages ============ */
.page-associations .join-association { margin-bottom: 18px; }
.page-associations .join-form { display: flex; gap: 8px; }
.page-associations .join-form input {
  flex: 1; padding: 9px 12px;
  border: 1px solid var(--border); border-radius: 6px;
  font-family: ui-monospace, Menlo, monospace; font-size: 13px; letter-spacing: .5px;
  text-transform: uppercase;
}
.assoc-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(260px, 1fr)); gap: 14px; }
.assoc-card {
  display: block;
  background: #fff;
  border: 1px solid var(--border, #d4d7dc);
  border-radius: 10px;
  padding: 16px 18px;
  text-decoration: none;
  color: inherit;
  transition: transform .12s, box-shadow .12s, border-color .12s;
}
.assoc-card:hover { transform: translateY(-1px); box-shadow: 0 6px 18px rgba(0,0,0,.08); border-color: #aab0b8; }
.assoc-card-head { display: flex; align-items: center; justify-content: space-between; gap: 8px; margin-bottom: 6px; }
.assoc-card-head h3 { margin: 0; font-size: 16px; }
.assoc-card-meta { font-size: 13px; color: #5b6068; }
.empty-state { padding: 24px 0; color: #5b6068; font-size: 14px; }

.chip {
  display: inline-block;
  font-size: 11px; font-weight: 600;
  padding: 2px 8px; border-radius: 100px;
  background: #e7e9ec; color: #5b6068;
  text-transform: uppercase; letter-spacing: .5px;
}
.chip-admin { background: var(--red, #7c5cff); color: #fff; }
.chip-owner { background: #ffb43a; color: #2c3036; }

/* ============ Association detail page ============ */
.page-association .assoc-header { align-items: center; gap: 16px; }
.assoc-header-main { display: flex; align-items: center; gap: 14px; }
.assoc-logo {
  width: 56px; height: 56px; border-radius: 8px;
  background: #2c3036 center/cover no-repeat;
  color: #fff; display: flex; align-items: center; justify-content: center;
  font-weight: 700; font-size: 22px;
}
.tabs {
  display: flex; gap: 4px;
  border-bottom: 1px solid var(--border, #d4d7dc);
  margin: 14px 0 18px;
}
.tabs .tab {
  background: transparent; border: none; padding: 10px 14px;
  font-size: 14px; font-weight: 500; color: #5b6068;
  border-bottom: 2px solid transparent;
  cursor: pointer;
}
.tabs .tab:hover { color: #111; }
.tabs .tab.active { color: var(--red, #7c5cff); border-bottom-color: var(--red, #7c5cff); }
.tab-panel[hidden] { display: none; }
.panel-toolbar { display: flex; align-items: center; gap: 10px; margin-bottom: 14px; flex-wrap: wrap; }
.panel-toolbar .sub { font-size: 12.5px; color: #777; }
.team-row, .member-row {
  display: flex; align-items: center; justify-content: space-between;
  padding: 12px 14px;
  background: #fff;
  border: 1px solid var(--border, #d4d7dc);
  border-radius: 8px;
  margin-bottom: 8px;
}
.team-row-name, .member-row-name { font-weight: 600; font-size: 14px; }
.team-row-link {
  color: #111;
  text-decoration: none;
  cursor: pointer;
}
.team-row-link:hover { color: var(--red, #7c5cff); text-decoration: underline; }
.team-row-meta, .member-row-meta { font-size: 12.5px; color: #5b6068; margin-top: 2px; }
.team-row-actions, .member-row-actions { display: flex; align-items: center; gap: 8px; }
.role-select { padding: 4px 6px; border-radius: 4px; border: 1px solid var(--border); font-size: 12.5px; }
.btn-sm { padding: 4px 10px; font-size: 12px; }
.invite-block { display: inline-flex; align-items: center; gap: 8px; padding: 6px 10px; background: #f5f6f7; border-radius: 6px; }
.invite-block .lbl { font-size: 12px; color: #5b6068; text-transform: uppercase; letter-spacing: .3px; }
.invite-block code { font-family: ui-monospace, Menlo, monospace; font-size: 13px; letter-spacing: .8px; }

/* Attach-team modal */
.attach-mode-tabs { display: flex; gap: 2px; background: #f0f2f4; padding: 2px; border-radius: 6px; margin: 10px 0; }
.mode-tab {
  flex: 1; padding: 7px 10px; border: none; background: transparent;
  border-radius: 4px; font-size: 12.5px; font-weight: 500; cursor: pointer; color: #5b6068;
}
.mode-tab.active { background: #fff; color: #111; box-shadow: 0 1px 2px rgba(0,0,0,.08); }

.danger-card { margin-top: 18px; border-left: 4px solid var(--danger, #dc2626); }
.btn-danger { background: var(--danger, #dc2626); color: #fff; border: none; }
.btn-danger:hover { background: #b8281f; }

.full-row { display: block; }
.full-row textarea { width: 100%; padding: 10px 12px; border: 1px solid var(--border); border-radius: 4px; font-family: inherit; font-size: 13px; }

/* Member title inline editor on Team page */
.title-input {
  width: 100%;
  padding: 5px 8px;
  border: 1px solid var(--border, #d4d7dc);
  border-radius: 4px;
  font-size: 13px;
  background: #fff;
}
.title-input:focus {
  border-color: var(--red, #7c5cff);
  outline: none;
}

/* ============ Schedule page (was Games) ============ */
.schedule-type-tabs {
  display: flex; gap: 2px;
  background: #eef0f3;
  padding: 2px;
  border-radius: 6px;
}
.schedule-type-tabs .type-tab {
  padding: 6px 12px;
  border: none;
  background: transparent;
  border-radius: 4px;
  font-size: 12.5px;
  font-weight: 500;
  color: #5b6068;
  cursor: pointer;
}
.schedule-type-tabs .type-tab:hover { color: #111; }
.schedule-type-tabs .type-tab.active {
  background: #fff;
  color: #111;
  box-shadow: 0 1px 2px rgba(0,0,0,0.06);
}

/* Type radios inside the schedule entry modal */
.entry-type-row { display: flex; gap: 6px; margin-bottom: 14px; }
.entry-type-opt {
  flex: 1;
  display: flex; align-items: center; gap: 6px;
  padding: 8px 10px;
  border: 1px solid var(--border, #d4d7dc);
  border-radius: 6px;
  font-size: 13px; font-weight: 500;
  cursor: pointer;
  background: #fff;
}
.entry-type-opt:has(input:checked) {
  border-color: var(--red, #7c5cff);
  background: #fff7f6;
  color: #111;
}
.entry-type-opt input { margin: 0; }

/* ============ Drill sharing ============ */
.inbox-link,
.account-link {
  position: relative;
  display: inline-flex; align-items: center; justify-content: center;
  width: 34px; height: 34px;
  margin-right: 6px;
  border-radius: 6px;
  color: inherit; text-decoration: none;
  transition: background 0.12s;
}
.inbox-link:hover,
.account-link:hover { background: rgba(255,255,255,0.10); }
.inbox-badge {
  position: absolute; top: 2px; right: 2px;
  min-width: 16px; height: 16px; padding: 0 4px;
  background: var(--red, #7c5cff); color: #fff;
  border-radius: 100px;
  font-size: 10px; font-weight: 700;
  display: inline-flex; align-items: center; justify-content: center;
  line-height: 1;
}
.inbox-badge[hidden] { display: none !important; }

.drill-card .acts .share,
.drill-card .acts .offline {
  display: inline-flex; align-items: center; justify-content: center;
  padding: 4px; border: none; background: transparent; cursor: pointer;
  color: #5b6068; border-radius: 4px;
}
.drill-card .acts .share:hover,
.drill-card .acts .offline:hover { background: rgba(0,0,0,0.06); color: #111; }
/* Pinned-for-offline state — filled cloud-check icon in the brand color
 * so it's distinct from the outlined "unpinned" default. */
.drill-card .acts .offline.offline--active { color: var(--brand-primary, #16a34a); }
.drill-card .acts .offline.offline--active:hover { color: var(--brand-primary, #16a34a); background: rgba(22,163,74,0.10); }

/* Legacy selectors kept for compatibility outside share modal; share
   modal overrides below scope to .share-modal and ID #share-modal. */
.share-tabs {
  display: flex; gap: 2px;
  background: #eef0f3; padding: 2px;
  border-radius: 6px;
  margin-bottom: 12px;
}
.share-tab {
  flex: 1; padding: 7px 10px; border: none; background: transparent;
  border-radius: 4px; font-size: 12.5px; font-weight: 500; cursor: pointer; color: #5b6068;
}
.share-tab.active { background: #fff; color: #111; box-shadow: 0 1px 2px rgba(0,0,0,0.06); }
.share-link-row { display: flex; gap: 8px; align-items: center; margin-top: 6px; }
.share-link-row input {
  flex: 1;
  padding: 9px 12px;
  border: 1px solid var(--border, #d4d7dc);
  border-radius: 6px;
  font-family: ui-monospace, Menlo, monospace;
  font-size: 12px;
}

/* ============================================================
   Share modal — premium pass.
   Polished tabs, refined inputs, brand-gradient CTA, dialogue
   chrome that matches the rest of Coachly.
   ============================================================ */
.share-modal {
  padding: 0 !important;
  border-radius: 18px;
  overflow: hidden;
}
.share-modal-head {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 12px;
  padding: 22px 24px 18px;
  border-bottom: 1px solid rgba(15, 23, 42, 0.06);
  background: linear-gradient(180deg, rgba(108, 92, 231, 0.04), transparent);
}
.share-modal-head-main {
  display: flex;
  align-items: center;
  gap: 12px;
  min-width: 0;
}
.share-modal-icon {
  width: 38px; height: 38px;
  border-radius: 11px;
  display: inline-flex; align-items: center; justify-content: center;
  background: var(--brand-primary, #7c5cff);
  color: #fff;
  box-shadow: 0 4px 12px color-mix(in srgb, var(--brand-primary, #7c5cff) 28%, transparent);
  flex-shrink: 0;
}
.share-modal-icon svg { width: 18px; height: 18px; }
.share-modal h3#share-modal-title {
  margin: 0 0 2px;
  font-size: 17px;
  font-weight: 700;
  letter-spacing: -0.01em;
  color: var(--text, #0f172a);
  line-height: 1.25;
}
.share-modal-sub {
  font-size: 12.5px;
  color: rgba(15, 23, 42, 0.55);
  line-height: 1.4;
}
.share-modal-x {
  width: 32px; height: 32px;
  border: 0;
  background: rgba(15, 23, 42, 0.04);
  color: rgba(15, 23, 42, 0.55);
  border-radius: 8px;
  display: inline-flex; align-items: center; justify-content: center;
  cursor: pointer;
  transition: background 150ms, color 150ms;
  flex-shrink: 0;
}
.share-modal-x:hover { background: rgba(15, 23, 42, 0.08); color: var(--text, #0f172a); }
.share-modal-x svg { width: 14px; height: 14px; }

/* Tab strip — refined segmented pill, brand-tinted active state. */
#share-modal .share-tabs {
  display: flex;
  gap: 2px;
  margin: 16px 24px 0;
  padding: 4px;
  background: rgba(15, 23, 42, 0.04);
  border-radius: 11px;
  border: 1px solid rgba(15, 23, 42, 0.04);
}
#share-modal .share-tab {
  flex: 1;
  padding: 9px 12px;
  border: 0;
  background: transparent;
  border-radius: 8px;
  font: inherit;
  font-size: 13px;
  font-weight: 600;
  color: rgba(15, 23, 42, 0.6);
  cursor: pointer;
  transition: background 150ms, color 150ms, box-shadow 150ms;
}
#share-modal .share-tab:hover { color: var(--text, #0f172a); }
#share-modal .share-tab.active {
  background: #fff;
  color: var(--text, #0f172a);
  box-shadow:
    0 1px 0 rgba(108, 92, 231, 0.06) inset,
    0 1px 3px rgba(15, 23, 42, 0.08),
    0 0 0 1px rgba(108, 92, 231, 0.12);
}

/* Pane container — consistent padding around content */
#share-modal .share-pane {
  padding: 18px 24px 22px;
}
.share-pane-hint {
  margin: 0 0 14px;
  font-size: 13px;
  color: rgba(15, 23, 42, 0.6);
  line-height: 1.5;
}
.share-field-label {
  display: block;
  font-size: 11.5px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  color: rgba(15, 23, 42, 0.5);
  margin: 14px 0 6px;
}
.share-field-label:first-child { margin-top: 0; }
.share-field-optional {
  font-size: 10.5px;
  font-weight: 600;
  letter-spacing: 0.03em;
  color: rgba(15, 23, 42, 0.35);
  margin-left: 4px;
  text-transform: none;
}

/* Inputs / textarea / select — softer, brand focus ring. */
#share-modal input[type="text"],
#share-modal input[type="email"],
#share-modal textarea,
#share-modal select {
  width: 100%;
  padding: 11px 14px;
  font: inherit;
  font-size: 13.5px;
  border: 1px solid rgba(15, 23, 42, 0.10);
  border-radius: 10px;
  background: #fafbff;
  color: var(--text, #0f172a);
  transition: border-color 150ms, box-shadow 150ms, background 150ms;
  outline: 0;
  box-sizing: border-box;
}
#share-modal input[type="text"]:focus,
#share-modal input[type="email"]:focus,
#share-modal textarea:focus,
#share-modal select:focus {
  border-color: var(--brand-primary, #7c5cff);
  background: #fff;
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--brand-primary, #7c5cff) 14%, transparent);
}
#share-modal textarea { resize: vertical; min-height: 60px; }

/* Action row + primary CTA — flat team brand with shimmer hover */
.share-pane-actions {
  display: flex;
  justify-content: flex-end;
  gap: 10px;
  margin-top: 18px;
}
.share-cta-btn {
  position: relative;
  display: inline-flex; align-items: center; gap: 8px;
  padding: 11px 20px;
  border: 0;
  border-radius: 11px;
  background: var(--brand-primary, #7c5cff);
  color: #fff;
  font: inherit;
  font-size: 13.5px;
  font-weight: 700;
  cursor: pointer;
  box-shadow:
    0 1px 0 rgba(255, 255, 255, 0.25) inset,
    0 6px 18px -4px color-mix(in srgb, var(--brand-primary, #7c5cff) 42%, transparent),
    0 2px 6px color-mix(in srgb, var(--brand-primary, #7c5cff) 18%, transparent);
  transition: transform 160ms cubic-bezier(.3, .9, .4, 1.1),
              box-shadow 160ms cubic-bezier(.3, .9, .4, 1.1);
  overflow: hidden;
  isolation: isolate;
}
.share-cta-btn::before {
  content: '';
  position: absolute; inset: 0;
  background: linear-gradient(120deg, transparent 35%, rgba(255,255,255,0.28) 50%, transparent 65%);
  transform: translateX(-120%);
  transition: transform 580ms cubic-bezier(.3, .9, .4, 1.1);
  pointer-events: none;
  z-index: -1;
}
.share-cta-btn:hover {
  transform: translateY(-1px);
  box-shadow:
    0 1px 0 rgba(255, 255, 255, 0.35) inset,
    0 10px 24px -6px color-mix(in srgb, var(--brand-primary, #7c5cff) 52%, transparent),
    0 3px 8px color-mix(in srgb, var(--brand-primary, #7c5cff) 22%, transparent);
}
.share-cta-btn:hover::before { transform: translateX(120%); }
.share-cta-btn:active { transform: translateY(0); }
.share-cta-btn:disabled { opacity: 0.55; cursor: progress; filter: saturate(0.55); }
.share-cta-btn:focus-visible {
  outline: 3px solid color-mix(in srgb, var(--brand-primary, #7c5cff) 40%, transparent);
  outline-offset: 2px;
}
.share-cta-btn svg { width: 15px; height: 15px; }

/* My-teams list — brand-tinted hover replaces the red */
#share-modal .push-to-teams-list { max-height: 320px; overflow-y: auto; }
#share-modal .push-team-row {
  border: 1px solid rgba(15, 23, 42, 0.08);
  border-radius: 10px;
  padding: 10px 14px;
  font-size: 13.5px;
  margin-bottom: 6px;
  background: #fff;
}
#share-modal .push-team-row:hover {
  background: color-mix(in srgb, var(--brand-primary, #7c5cff) 5%, transparent);
  border-color: color-mix(in srgb, var(--brand-primary, #7c5cff) 30%, transparent);
}
#share-modal .push-team-row input[type="checkbox"] {
  width: 16px; height: 16px;
  accent-color: var(--brand-primary, #7c5cff);
}

/* Link tab — URL row + Copy/Regen */
#share-modal .share-link-row {
  display: flex;
  gap: 8px;
  align-items: stretch;
  margin-top: 8px;
}
#share-modal .share-link-row input {
  flex: 1;
  padding: 11px 14px;
  border: 1px solid rgba(15, 23, 42, 0.10);
  border-radius: 10px;
  font-family: ui-monospace, "SF Mono", Menlo, monospace;
  font-size: 12px;
  background: #fafbff;
  color: rgba(15, 23, 42, 0.85);
}
#share-modal .share-link-row input:focus { border-color: var(--brand-primary, #7c5cff); background: #fff; }
.share-link-copy-btn {
  display: inline-flex; align-items: center; gap: 7px;
  padding: 0 16px;
  border: 0;
  border-radius: 10px;
  background: var(--brand-primary, #7c5cff);
  color: #fff;
  font: inherit;
  font-size: 13px;
  font-weight: 700;
  cursor: pointer;
  box-shadow: 0 4px 12px -2px color-mix(in srgb, var(--brand-primary, #7c5cff) 35%, transparent);
  transition: transform 150ms, box-shadow 150ms, filter 150ms;
}
.share-link-copy-btn:hover { transform: translateY(-1px); box-shadow: 0 6px 16px -3px color-mix(in srgb, var(--brand-primary, #7c5cff) 45%, transparent); }
.share-link-copy-btn svg { width: 14px; height: 14px; }
.share-link-copy-btn--copied { filter: saturate(0.8) brightness(1.05); }

#share-modal .share-link-regen {
  width: 42px;
  padding: 0;
  border: 1px solid rgba(15, 23, 42, 0.10);
  background: #fafbff;
  color: rgba(15, 23, 42, 0.55);
  border-radius: 10px;
  display: inline-flex; align-items: center; justify-content: center;
  cursor: pointer;
  transition: background 150ms, color 150ms, transform 200ms;
  flex-shrink: 0;
}
#share-modal .share-link-regen svg { width: 14px; height: 14px; }
#share-modal .share-link-regen:hover {
  background: #fff;
  color: var(--brand-primary, #7c5cff);
  transform: rotate(45deg);
}

/* Expiry segmented picker */
#share-modal .share-link-expiry {
  display: flex; align-items: center; gap: 10px;
  margin: 0 0 12px;
}
#share-modal .share-link-expiry-label {
  font-size: 11.5px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  color: rgba(15, 23, 42, 0.5);
}
#share-modal .share-link-expiry-segs {
  display: inline-flex;
  background: rgba(15, 23, 42, 0.05);
  border-radius: 999px;
  padding: 3px;
  gap: 2px;
}
#share-modal .share-link-expiry-seg {
  border: 0; background: transparent;
  padding: 6px 12px;
  border-radius: 999px;
  font: inherit;
  font-size: 12px;
  font-weight: 600;
  color: rgba(15, 23, 42, 0.6);
  cursor: pointer;
  transition: background 150ms, color 150ms, box-shadow 150ms;
}
#share-modal .share-link-expiry-seg:hover { color: var(--text, #0f172a); }
#share-modal .share-link-expiry-seg[aria-pressed="true"] {
  background: #fff;
  color: var(--text, #0f172a);
  box-shadow: 0 1px 3px rgba(15, 23, 42, 0.10);
}

/* Stats panel (link tab) */
#share-modal .share-link-stats {
  margin-top: 18px;
  padding-top: 16px;
  border-top: 1px solid rgba(15, 23, 42, 0.06);
}
#share-modal .share-link-stats-row {
  display: grid;
  grid-template-columns: 1fr 1fr 1fr;
  gap: 10px;
}
#share-modal .share-link-stat {
  background: rgba(15, 23, 42, 0.03);
  border: 1px solid rgba(15, 23, 42, 0.04);
  border-radius: 12px;
  padding: 12px 14px;
  text-align: center;
}
#share-modal .share-link-stat:first-child {
  background: linear-gradient(135deg, rgba(108, 92, 231, 0.08), rgba(0, 206, 201, 0.08));
  border-color: rgba(108, 92, 231, 0.18);
}
#share-modal .share-link-stat-num {
  display: block;
  font-size: 22px;
  font-weight: 800;
  color: var(--text, #0f172a);
  line-height: 1.05;
  font-variant-numeric: tabular-nums;
  letter-spacing: -0.01em;
}
#share-modal .share-link-stat:first-child .share-link-stat-num {
  color: var(--brand-primary, #7c5cff);
}
#share-modal .share-link-stat-label {
  font-size: 11px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: rgba(15, 23, 42, 0.5);
  margin-top: 4px;
  display: inline-block;
}
#share-modal .share-link-stat-expiry .share-link-stat-num { font-size: 17px; }

@media (max-width: 600px) {
  .share-modal { width: 96vw !important; }
  .share-modal-head { padding: 18px 18px 14px; }
  #share-modal .share-tabs { margin: 14px 18px 0; }
  #share-modal .share-pane { padding: 16px 18px 20px; }
  #share-modal .share-link-stats-row { grid-template-columns: 1fr; }
  #share-modal .share-link-expiry { flex-wrap: wrap; }
}

/* Inbox rows (used in both topnav modal and /inbox page) */
.inbox-row {
  display: flex; align-items: center; gap: 12px;
  padding: 12px;
  background: #fff;
  border: 1px solid var(--border, #d4d7dc);
  border-radius: 8px;
  margin-bottom: 8px;
}
.inbox-thumb {
  width: 64px; height: 64px;
  border-radius: 4px;
  background: #f5f6f7;
  object-fit: cover;
  flex: 0 0 auto;
}
.inbox-main { flex: 1; min-width: 0; }
.inbox-name { font-weight: 600; font-size: 14px; color: #111; }
.inbox-meta { font-size: 12.5px; color: #5b6068; margin-top: 2px; }
.inbox-message { font-size: 13px; color: #2c3036; margin-top: 4px; font-style: italic; }
.inbox-actions { display: flex; gap: 6px; flex-direction: column; }
.inbox-actions .btn { padding: 5px 10px; font-size: 12.5px; }

.inbox-status-tabs { display: flex; gap: 2px; background: #eef0f3; padding: 2px; border-radius: 6px; }
.inbox-status-tabs .status-tab {
  padding: 6px 12px; border: none; background: transparent;
  border-radius: 4px; font-size: 12.5px; font-weight: 500; color: #5b6068; cursor: pointer;
}
.inbox-status-tabs .status-tab.active { background: #fff; color: #111; box-shadow: 0 1px 2px rgba(0,0,0,0.06); }

.share-card .share-card-grid {
  display: grid;
  grid-template-columns: 200px 1fr;
  gap: 18px;
}
.share-thumb {
  width: 100%; aspect-ratio: 1.5 / 1;
  background: #f5f6f7;
  border-radius: 6px;
  object-fit: cover;
}
.share-meta h2 { margin: 0 0 6px 0; }
.share-meta-row { display: flex; gap: 6px; flex-wrap: wrap; margin-bottom: 8px; }
.share-description { font-size: 13px; color: #2c3036; }
.share-owner { margin-top: 10px; }

/* ============ Attendance modal (schedule entry) ============ */
.attendance-bulk-row {
  display: flex; align-items: center; gap: 6px; flex-wrap: wrap;
  padding: 8px 0 12px;
  margin-bottom: 8px;
  border-bottom: 1px solid var(--border-soft, #eef0f3);
}
.attendance-table .att-status {
  width: 100%;
  padding: 4px 6px;
  border: 1px solid var(--border, #d4d7dc);
  border-radius: 4px;
  font-size: 12.5px;
  background: #fff;
}
.attendance-table .att-row.status-going     { background: rgba(34,197,94,.08); }
.attendance-table .att-row.status-maybe     { background: rgba(255,180,58,.10); }
.attendance-table .att-row.status-not_going { background: rgba(124, 92, 255,.08); }
.attendance-table .att-row.status-attended  { background: rgba(40,100,200,.07); }
.attendance-table .att-row.status-absent    { background: rgba(124, 92, 255,.12); }

/* Both boxes set display:flex, which beats the UA [hidden] rule — the
 * read-only (parent) modal hides them via the attribute. */
.attendance-rsvp[hidden], .attendance-bulk-row[hidden] { display: none; }

/* Player milestones & badges */
.pp-badges-card { display: flex; flex-wrap: wrap; gap: 10px; }
.pp-badge {
  display: inline-flex; align-items: center; gap: 9px;
  padding: 8px 14px 8px 10px; border-radius: 12px;
  background: var(--bg-soft, #f6f7f9); border: 1px solid var(--border, #e2e5ea);
}
.pp-badge-ico {
  width: 30px; height: 30px; border-radius: 50%; flex: none;
  background: var(--brand-primary, #d4302b); color: #fff;
  display: inline-flex; align-items: center; justify-content: center;
}
.pp-badge-ico svg { width: 16px; height: 16px; }
.pp-badge-body { display: flex; flex-direction: column; line-height: 1.25; }
.pp-badge-body b { font-size: 13px; color: var(--text, #1a1d23); }
.pp-badge-body span { font-size: 11.5px; color: var(--text-dim, #5a6270); }

/* ============ Schedule list v2 — flat rows, month groups ============ */
.sched-list { padding: 4px 0 8px; }
.sched-month {
  padding: 18px 24px 8px;
  font-size: 11.5px; font-weight: 800; letter-spacing: 0.08em; text-transform: uppercase;
  color: var(--text-dim, #5a6270);
  border-bottom: 1px solid var(--border-soft, #eef0f3);
}
.sched-past-divider {
  display: flex; align-items: center; gap: 12px;
  padding: 22px 24px 2px;
}
.sched-past-divider::before, .sched-past-divider::after {
  content: ''; flex: 1; height: 1px; background: var(--border, #e2e5ea);
}
.sched-past-divider span {
  font-size: 11.5px; font-weight: 800; letter-spacing: 0.1em; text-transform: uppercase;
  color: var(--text-dim, #5a6270);
}
.sched-row {
  display: flex; align-items: center; gap: 14px;
  padding: 13px 24px;
  border-bottom: 1px solid var(--border-soft, #eef0f3);
  border-left: 3px solid transparent;
}
.sched-row:hover { background: var(--bg-soft, #f8f9fb); }
.sched-row.row-openable { cursor: pointer; }
.sched-row.sched-next { border-left-color: var(--brand-primary, #d4302b); background: color-mix(in srgb, var(--brand-primary, #d4302b) 3%, #fff); }
.sched-row.sched-next:hover { background: color-mix(in srgb, var(--brand-primary, #d4302b) 6%, #fff); }
.sched-date {
  display: flex; flex-direction: column; align-items: center; flex: none; width: 40px;
}
.sched-dow { font-size: 10.5px; font-weight: 700; letter-spacing: 0.06em; text-transform: uppercase; color: var(--text-dim, #5a6270); }
.sched-day { font-size: 20px; font-weight: 800; line-height: 1.1; color: var(--text, #1a1d23); font-variant-numeric: tabular-nums; }
.sched-today .sched-day { color: var(--brand-primary, #d4302b); }
.sched-type {
  flex: none; width: 34px; height: 34px; border-radius: 9px;
  display: flex; align-items: center; justify-content: center;
  background: var(--bg-soft, #f2f4f7); border: 1px solid var(--border-soft, #e7eaee);
  color: var(--text-dim, #5a6270);
}
.sched-next .sched-type { background: #fff; }
.sched-type svg { width: 17px; height: 17px; }
.sched-main { flex: 1; min-width: 0; }
.sched-title { font-size: 15px; font-weight: 700; color: var(--text, #1a1d23); }
.sched-sub { font-size: 12.5px; color: var(--text-dim, #5a6270); margin-top: 1px; }
.sched-sub .venue-dir { font-weight: 700; }
.sched-meta { margin-top: 4px; display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
.sched-meta .last-meeting { font-size: 12px; color: var(--text-dim, #5a6270); }
.sched-right { flex: none; display: flex; align-items: center; gap: 8px; }
.sched-score { font-size: 16px; font-weight: 800; color: var(--text, #1a1d23); font-variant-numeric: tabular-nums; }
.sched-score.loss { color: var(--text-dim, #5a6270); }
.sched-next-pill {
  padding: 3px 10px; border-radius: 999px;
  background: var(--brand-primary, #d4302b); color: #fff;
  font-size: 10.5px; font-weight: 800; letter-spacing: 0.08em; text-transform: uppercase;
  white-space: nowrap;
}
.sched-actions { flex: none; display: flex; align-items: center; gap: 6px; flex-wrap: wrap; justify-content: flex-end; }
.sched-actions .action-btn {
  font-size: 12px; padding: 5px 10px; border-radius: 8px;
  border: 1px solid var(--border, #d9dde3); background: #fff;
  color: var(--text, #1a1d23); cursor: pointer; font-weight: 600;
  display: inline-flex; align-items: center; gap: 5px;
}
.sched-actions .action-btn:hover { border-color: var(--text-dim, #5a6270); }
body.route-schedule .sched-actions .action-btn.primary {
  background: var(--brand-primary, #d4302b); border-color: var(--brand-primary, #d4302b); color: #fff;
}
body.route-schedule .sched-actions .action-btn.primary:hover { filter: brightness(0.95); }
.sched-actions .action-btn svg, .sched-actions .action-btn .icon-inline { width: 13px; height: 13px; }
@media (max-width: 700px) {
  .sched-row { flex-wrap: wrap; padding: 12px 14px; gap: 10px; row-gap: 8px; }
  .sched-month, .sched-past-divider { padding-left: 14px; padding-right: 14px; }
  .sched-main { flex: 1 1 55%; }
  .sched-actions { flex-basis: 100%; justify-content: flex-start; }
}

/* Overlapped who's-going avatar stack on schedule rows */
.att-stack { display: inline-flex; align-items: center; vertical-align: middle; margin-right: 2px; }
.att-stack .att-ava {
  width: 20px; height: 20px; border-radius: 50%;
  background: var(--brand-primary, #d4302b); color: #fff;
  font-size: 8.5px; font-weight: 800; letter-spacing: 0.02em;
  display: inline-flex; align-items: center; justify-content: center;
  border: 2px solid var(--bg, #fff); margin-left: -7px;
  box-sizing: content-box;
}
.att-stack .att-ava:first-child { margin-left: 0; }
.att-stack .att-ava-more { background: var(--bg-soft, #f2f4f7); color: var(--text, #1a1d23); border-color: var(--border, #d4d7dc); }

/* Read-only who's-going view (parents & players) */
.att-ro-chips { display: flex; gap: 6px; flex-wrap: wrap; padding: 2px 0 12px; }
.att-chip {
  display: inline-block; padding: 3px 10px; border-radius: 999px;
  font-size: 12px; font-weight: 700;
  background: var(--bg-soft, #f2f4f7); color: var(--text, #1a1d23);
  border: 1px solid var(--border, #d4d7dc);
}
.att-chip-going     { background: rgba(34,197,94,.12);  border-color: rgba(34,197,94,.35);  color: #157347; }
.att-chip-maybe     { background: rgba(255,180,58,.14); border-color: rgba(255,180,58,.4);  color: #92600a; }
.att-chip-not_going { background: rgba(220,64,64,.10);  border-color: rgba(220,64,64,.3);   color: #a33030; }
.att-ro-group { margin-bottom: 12px; }
.att-ro-head {
  font-size: 11.5px; font-weight: 800; letter-spacing: .04em; text-transform: uppercase;
  color: var(--text-dim, #5a6270); padding: 6px 2px; border-bottom: 1px solid var(--border-soft, #eef0f3);
}
.att-ro-head-going { color: #157347; }
.att-ro-head-maybe { color: #92600a; }
.att-ro-head-not_going { color: #a33030; }
.att-ro-row {
  display: flex; align-items: center; gap: 10px;
  padding: 7px 2px; border-bottom: 1px solid var(--border-soft, #eef0f3);
  font-size: 13.5px;
}
.att-ro-row:last-child { border-bottom: 0; }
.att-ro-num { min-width: 26px; color: var(--text-dim, #5a6270); font-variant-numeric: tabular-nums; }
.att-ro-pos { margin-left: auto; color: var(--text-dim, #5a6270); font-size: 12px; }
@media (prefers-color-scheme: dark) {
  .att-chip-going     { color: #7ddba4; }
  .att-chip-maybe     { color: #f0c377; }
  .att-chip-not_going { color: #f09a9a; }
  .att-ro-head-going { color: #7ddba4; }
  .att-ro-head-maybe { color: #f0c377; }
  .att-ro-head-not_going { color: #f09a9a; }
}

/* ============ Bulk-setup AI modal ============ */
.bulk-modal { width: 560px; max-width: 92vw; }
.bulk-label {
  display: block;
  font-size: 12px; font-weight: 600;
  color: var(--text-dim, #5b6068);
  text-transform: uppercase; letter-spacing: .5px;
  margin-bottom: 6px;
}
#bulk-text {
  width: 100%;
  border: 1px solid var(--border, #d4d7dc);
  border-radius: 6px;
  padding: 10px 12px;
  font-family: inherit; font-size: 13px;
  resize: vertical; min-height: 110px;
}
.bulk-csv-row { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
.bulk-csv-row .sub { font-size: 12.5px; color: #5b6068; }

.bulk-loading { display: flex; flex-direction: column; align-items: center; gap: 12px; padding: 28px 12px; text-align: center; }
.bulk-loading .busy-spinner { width: 38px; height: 38px; }

.bulk-review-list { display: flex; flex-direction: column; gap: 6px; max-height: 380px; overflow-y: auto; padding: 2px; }
.bulk-review-row {
  display: flex; align-items: center; gap: 10px;
  padding: 10px 12px;
  background: #f5f6f7;
  border: 1px solid transparent;
  border-radius: 6px;
  cursor: pointer;
  transition: background .12s, border-color .12s;
}
.bulk-review-row.selected { background: #fff; border-color: var(--red, #7c5cff); }
.bulk-review-row input[type="checkbox"] { flex: 0 0 auto; }
.bulk-review-main { flex: 1; min-width: 0; }
.bulk-review-name { font-weight: 600; font-size: 14px; color: #111; }
.bulk-review-meta { display: flex; gap: 12px; flex-wrap: wrap; font-size: 12.5px; color: #5b6068; margin-top: 2px; }

/* Photo-import settings popover (model toggle). */
.import-photo-group { position: relative; display: inline-flex; align-items: center; gap: 2px; }
.import-photo-settings svg { width: 14px; height: 14px; }
.import-photo-settings { padding: 4px 5px !important; }
.import-photo-menu {
  /* Fixed so the menu escapes the topbar's overflow-x (which implicitly clips
     the Y axis). JS sets top/left based on the gear button's viewport rect. */
  position: fixed;
  top: 0; left: 0;
  background: #fff;
  border: 1px solid var(--border, #d4d7dc);
  border-radius: 8px;
  box-shadow: 0 8px 24px rgba(0,0,0,.18);
  padding: 10px 12px;
  min-width: 280px;
  z-index: 1500;
  font-size: 13px;
  color: #2c3036;
}
.import-photo-menu[hidden] { display: none; }
.import-photo-menu-title { font-weight: 600; font-size: 12px; color: #555; letter-spacing: .3px; text-transform: uppercase; margin-bottom: 6px; }
.import-photo-menu-row {
  display: flex; align-items: center; gap: 8px;
  padding: 6px 4px;
  cursor: pointer;
}
.import-photo-menu-row:hover { background: #f5f6f7; border-radius: 4px; }
.import-photo-menu-row input[type="radio"] { margin: 0; }
.import-photo-menu-row .muted { color: #888; font-size: 11.5px; margin-left: auto; }
.import-photo-menu-hint { font-size: 11.5px; color: #777; margin-top: 6px; line-height: 1.3; }

/* Full-viewport busy overlay (used by the photo-import flow; reusable for
   any long-running operation that needs to block the canvas). */
/* Busy overlay — Emil polish: opacity-based show/hide so we can transition
   the entry/exit. Card scales from 0.96 + opacity 0 so it materializes
   instead of popping. Spinner is 0.7s — a hair faster than the previous
   0.9s, which makes loading feel snappier.
   iPad fix (2026-05-30): added `visibility: hidden` so iOS Safari truly
   skips hit-testing on the overlay when it's not visible. Without this,
   backdrop-filter creates a stacking context that intercepts ALL touches
   in the viewport — including the style bar at the bottom of the drill
   board — even with pointer-events: none. The `transition: visibility
   0s linear 200ms` delay keeps the element rendered through the fade-out. */
.busy-overlay {
  position: fixed;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  background: rgba(20, 22, 26, 0.5);
  z-index: 2000;
  opacity: 0;
  visibility: hidden;
  pointer-events: none;
  transition:
    opacity 200ms ease-out,
    visibility 0s linear 200ms;
}
.busy-overlay.show {
  opacity: 1;
  visibility: visible;
  pointer-events: auto;
  /* Only apply the backdrop-filter when actually visible — on iOS Safari
     a transparent backdrop-filter STILL captures input even with
     visibility: hidden, so we conditionally enable it via .show. */
  backdrop-filter: blur(2px);
  -webkit-backdrop-filter: blur(2px);
  /* Override the visibility-delay transition so it shows instantly. */
  transition: opacity 200ms ease-out;
}
.busy-overlay .busy-card {
  background: #fff;
  padding: 28px 36px;
  border-radius: 12px;
  box-shadow: 0 12px 40px rgba(0,0,0,0.3);
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 14px;
  max-width: 340px;
  text-align: center;
  transform: scale(0.96);
  opacity: 0;
  transition:
    transform 260ms cubic-bezier(0.23, 1, 0.32, 1),
    opacity 220ms ease-out;
}
.busy-overlay.show .busy-card {
  transform: scale(1);
  opacity: 1;
}
.busy-overlay .busy-spinner {
  width: 44px;
  height: 44px;
  border: 4px solid #e7e9ec;
  border-top-color: var(--brand-primary, #7c5cff);
  border-radius: 50%;
  animation: busy-spin 0.7s linear infinite;
}
@keyframes busy-spin { to { transform: rotate(360deg); } }
@media (prefers-reduced-motion: reduce) {
  .busy-overlay,
  .busy-overlay .busy-card {
    transition: opacity 180ms ease-out;
    transform: none;
  }
  .busy-overlay.show .busy-card { transform: none; }
}

/* ============================================================
   AUTO LIST-LOADING SPINNERS
   ============================================================
   These content containers start empty in the server-rendered HTML
   and get populated by JS once api.me() returns. To avoid showing a
   blank area during that gap (~300-500ms typical, longer on first
   load via the Cloudflare tunnel), we use the :empty pseudo-class
   to render a spinner inside any of these containers automatically
   — and it disappears the moment JS inserts any child node.

   No JS changes needed. Add a container's id/class here if it
   suffers the same "blank during boot" symptom.
   ============================================================ */
#drill-list:empty::before,
#plan-list:empty::before,
#plan-grid:empty::before,
#game-list:empty::before,
#drill-picker:empty::before,
#inbox-list:empty::before {
  content: '';
  display: block;
  width: 28px;
  height: 28px;
  margin: 36px auto 8px;
  border: 3px solid #e7e9ec;
  border-top-color: var(--brand-primary, #7c5cff);
  border-radius: 50%;
  animation: busy-spin 0.9s linear infinite;
}
#drill-list:empty::after,
#plan-list:empty::after,
#plan-grid:empty::after,
#game-list:empty::after,
#drill-picker:empty::after,
#inbox-list:empty::after {
  content: 'Loading…';
  display: block;
  text-align: center;
  font-size: 12px;
  color: var(--text-dim);
  letter-spacing: 0.3px;
  margin-bottom: 24px;
}
.busy-overlay .busy-message {
  font-size: 15px;
  font-weight: 600;
  color: #2c3036;
  letter-spacing: 0.2px;
}
.busy-overlay .busy-submessage {
  font-size: 13px;
  color: #5b6068;
  line-height: 1.4;
}

/* Drill tabs strip — lives in row 1 of the canvas column (grid placement
   handled in the main rule). Light theme so tabs read like a browser tab bar. */
.drill-tabs {
  display: flex;
  align-items: stretch;
  gap: 2px;
  padding: 0 4px;
  background: #e7e9ec;
  border-bottom: 1px solid #c9ccd1;
  min-height: 34px;
  overflow-x: auto;
  overflow-y: hidden;
  scrollbar-width: thin;
}
.drill-tab-list {
  display: flex;
  align-items: stretch;
  gap: 2px;
  flex: 0 0 auto;
}
.drill-tab {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 0 10px 0 12px;
  background: #d4d7dc;
  color: #3a3f46;
  border-radius: 6px 6px 0 0;
  font-size: 12.5px;
  font-weight: 500;
  white-space: nowrap;
  cursor: pointer;
  height: 30px;
  margin-top: 4px;
  border: 1px solid transparent;
  border-bottom: none;
  max-width: 200px;
  user-select: none;
}
.drill-tab:hover { background: #c8ccd1; }
.drill-tab.active {
  background: #ffffff;
  color: #111;
  border-color: #c9ccd1;
}
.drill-tab-name {
  overflow: hidden;
  text-overflow: ellipsis;
  max-width: 160px;
}
.drill-tab-close {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 18px; height: 18px;
  padding: 0;
  margin-right: -4px;
  border: none;
  background: transparent;
  border-radius: 50%;
  color: inherit;
  font-size: 16px;
  line-height: 1;
  cursor: pointer;
  opacity: 0.7;
}
.drill-tab-close:hover {
  background: rgba(0,0,0,0.1);
  opacity: 1;
}
.drill-tab-add {
  align-self: center;
  width: 26px; height: 26px;
  margin-left: 6px;
  border: none;
  background: transparent;
  color: #555a62;
  font-size: 18px;
  line-height: 1;
  border-radius: 4px;
  cursor: pointer;
}
.drill-tab-add:hover { background: #d4d7dc; color: #111; }

/* Custom hover tooltip (see tooltip.js) */
.pc-tooltip {
  position: fixed;
  top: 0; left: 0;
  pointer-events: none;
  background: rgba(24, 26, 32, 0.96);
  color: #fff;
  padding: 5px 9px;
  border-radius: 5px;
  font-size: 12px;
  font-weight: 500;
  line-height: 1.3;
  white-space: nowrap;
  max-width: 280px;
  box-shadow: 0 4px 14px rgba(0,0,0,0.18);
  letter-spacing: 0.2px;
  z-index: 10000;
  opacity: 0;
  transform: translateY(2px);
  transition: opacity 110ms ease, transform 110ms ease;
}
.pc-tooltip.show {
  opacity: 1;
  transform: translateY(0);
}

/* ============================================================
   MODERN UI REFRESH
   Token additions + surgical overrides for the highest-traffic
   shared surfaces (buttons, modals, inputs, cards, login, page
   header, tables, menus). Doesn't touch the drill-page toolbar,
   the schedule calendar, or other surfaces that already feel
   right — those stay untouched.
   ============================================================ */

:root {
  /* Radii */
  --r-xs:   3px;
  --r-sm:   4px;
  --r:      6px;
  --r-md:   8px;
  --r-lg:   12px;
  --r-pill: 999px;
  /* Layered shadows (low-opacity for a modern flat-with-depth feel). */
  --shadow-xs: 0 1px 2px rgba(15, 23, 42, 0.04), 0 1px 1px rgba(15, 23, 42, 0.03);
  --shadow-sm: 0 4px 12px -2px rgba(15, 23, 42, 0.06), 0 2px 4px -2px rgba(15, 23, 42, 0.04);
  --shadow:    0 10px 25px -5px rgba(15, 23, 42, 0.10), 0 4px 8px -4px rgba(15, 23, 42, 0.06);
  --shadow-lg: 0 24px 48px -12px rgba(15, 23, 42, 0.18), 0 8px 16px -8px rgba(15, 23, 42, 0.10);
  /* Standard focus ring — soft blue halo, accessible AA contrast. */
  --ring: 0 0 0 3px rgba(40, 100, 200, 0.22);
  --ring-danger: 0 0 0 3px rgba(124, 92, 255, 0.22);
  /* Motion */
  --ease: cubic-bezier(.16, 1, .3, 1);
  --t-fast: 120ms;
  --t: 180ms;
}

/* Typography polish — subtle, system-wide. */
/* Headlines use Instrument Sans for a slight display contrast against the
 * Geist body font. Same fallback chain so we degrade gracefully if Google
 * Fonts is slow. Letter-spacing is tightened slightly on display text. */
h1, h2, h3, h4 {
  font-family: 'Instrument Sans', 'Geist', -apple-system, BlinkMacSystemFont, sans-serif;
  letter-spacing: -0.015em;
}
.page-header h1 { font-size: 24px; font-weight: 700; }
.page-header .sub { font-size: 13px; color: var(--text-dim); margin-top: 4px; }

/* Buttons — softer corners, subtle shadow on primary, smooth transitions,
   accessible focus rings. */
.btn {
  border-radius: var(--r);
  font-weight: 500;
  transition: background var(--t-fast) var(--ease),
              border-color var(--t-fast) var(--ease),
              box-shadow var(--t-fast) var(--ease),
              transform var(--t-fast) var(--ease);
  box-shadow: var(--shadow-xs);
}
.btn:focus-visible { outline: none; box-shadow: var(--shadow-xs), var(--ring); }
.btn:active { transform: translateY(0.5px); }
.btn-primary {
  box-shadow: 0 1px 0 rgba(0, 0, 0, 0.08), inset 0 1px 0 rgba(255, 255, 255, 0.10);
}
.btn-primary:focus-visible { box-shadow: 0 1px 0 rgba(0,0,0,0.08), inset 0 1px 0 rgba(255,255,255,0.10), var(--ring); }
.btn-danger:focus-visible { box-shadow: 0 1px 0 rgba(0,0,0,0.08), var(--ring-danger); }

/* Inputs — consistent radii, soft focus ring instead of just a colour swap. */
.modal input, .modal select, .modal textarea,
.field input, .field select, .field textarea,
.login-form input,
.topbar input[type="text"], .topbar select {
  border-radius: var(--r);
  transition: border-color var(--t-fast) var(--ease), box-shadow var(--t-fast) var(--ease);
}
.modal input:focus, .modal select:focus, .modal textarea:focus,
.field input:focus, .field select:focus, .field textarea:focus,
.login-form input:focus,
.topbar input[type="text"]:focus, .topbar select:focus {
  border-color: var(--brand-secondary);
  box-shadow: var(--ring);
  outline: none;
}

/* Cards — cleaner border + layered shadow. */
.card {
  border-radius: var(--r-md);
  border-color: var(--border-soft);
  box-shadow: var(--shadow-xs);
  padding: 20px;
  margin-bottom: 16px;
  transition: box-shadow var(--t) var(--ease);
}
.card h2 { font-size: 16px; font-weight: 600; letter-spacing: -0.005em; }
.card .card-head { margin-bottom: 12px; }

/* Modals — softer shadow + slightly rounder corners + better breathing room. */
.modal {
  border-radius: var(--r-lg);
  padding: 28px;
  box-shadow: var(--shadow-lg);
}
.modal h3 { font-size: 19px; font-weight: 700; letter-spacing: -0.01em; margin: 0 0 16px 0; }
.modal-actions { margin-top: 24px; gap: 10px; }
/* Soft fade on the backdrop. */
.modal-bg {
  backdrop-filter: blur(2px);
  -webkit-backdrop-filter: blur(2px);
}

/* Tables — quieter zebra-free hover, slightly larger row padding. */
table.data-table th, table.data-table td { padding: 11px 12px; }
table.data-table th { font-size: 10.5px; letter-spacing: 0.6px; }
table.data-table tr:hover td { background: rgba(40, 100, 200, 0.03); }

/* Empty states — bigger but quieter, more deliberate hierarchy. */
.empty, .empty-state {
  padding: 72px 24px;
}
.empty .icon, .empty-state .icon {
  font-size: 40px;
  opacity: 0.5;
  margin-bottom: 12px;
  line-height: 1;
}
.empty, .empty-state { font-size: 14px; line-height: 1.5; }

/* Login screen — softer, brand-tinted dark backdrop instead of a hard
   diagonal gradient. Modern card with reduced shadow. */
.login-screen {
  background:
    radial-gradient(800px circle at 15% 10%, rgba(124, 92, 255, 0.18), transparent 55%),
    radial-gradient(700px circle at 85% 90%, rgba(40, 100, 200, 0.16), transparent 55%),
    #15171c;
}
.login-card {
  border-radius: var(--r-lg);
  box-shadow: var(--shadow-lg);
  padding: 36px 36px 32px;
}
.login-card h1 { font-size: 24px; font-weight: 700; letter-spacing: -0.015em; }
.login-card .logo .mark {
  box-shadow: 0 6px 16px -6px rgba(124, 92, 255, 0.45);
}

/* Topnav links — quieter inactive state, tighter spacing. */
.topnav-link {
  border-radius: var(--r);
  transition: background var(--t-fast), color var(--t-fast);
}

/* User chip — slightly tighter, with a modern focus ring. */
.user-chip { transition: background var(--t-fast); }
.user-chip:focus-visible { outline: none; box-shadow: var(--ring); }

/* Toast — float a touch more, smoother corners. */
.toast {
  border-radius: var(--r-md);
  box-shadow: var(--shadow);
  font-weight: 500;
  letter-spacing: 0.1px;
}

/* Drill folders / sidebar items — subtle hover, tighter corners. */
.drill-card { transition: background var(--t-fast), box-shadow var(--t-fast); }
.drill-card:hover { box-shadow: var(--shadow-xs); }

/* Generic dropdown menu shadow softening (rink menu, import menu, etc.). */
.rink-menu, .import-photo-menu, .line-ctx-menu {
  border-radius: var(--r-md);
  box-shadow: var(--shadow);
}

/* Result badges (W / L / OTL) — neater pill shape if you happen to use them. */
.result-w, .result-l, .result-otl, .result-t {
  display: inline-block;
  padding: 2px 8px;
  border-radius: var(--r-pill);
  font-weight: 600;
  font-size: 11px;
  letter-spacing: 0.4px;
  text-transform: uppercase;
}
.result-w  { background: rgba(31, 158, 90, 0.12);  color: #157a45; }
.result-l  { background: rgba(124, 92, 255, 0.12);  color: var(--red); }
.result-otl,
.result-t  { background: rgba(40, 100, 200, 0.12); color: var(--blue); }

/* Small inline SVG icons used in JS-rendered cells (schedule type, attendance).
   Keeps stroke crisp + matches body text color so they don't shout. */
.icon-inline {
  display: inline-block;
  width: 18px; height: 18px;
  vertical-align: -3px;
  color: var(--text);
}
.icon-inline.dim { color: var(--text-dim); }

/* Size adjustments for the inline SVG icons in different contexts. */
.btn .icon-inline,
.icon-btn .icon-inline { width: 15px; height: 15px; vertical-align: -2px; }
.cal-entry .icon-inline { width: 13px; height: 13px; vertical-align: -1px; }
table.data-table .icon-inline { vertical-align: -4px; }

/* ============================================================
   Goal-details modal extras (strength, shot type, goalie target)
   ============================================================ */
.strength-row {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 6px;
  margin-top: 4px;
}
.strength-opt {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 6px 8px;
  border: 1px solid var(--border, #d4d7dc);
  border-radius: var(--r, 6px);
  background: #fff;
  font-size: 12px;
  cursor: pointer;
  user-select: none;
  text-transform: none !important;
  letter-spacing: 0 !important;
  color: var(--text);
}
.strength-opt:hover { background: var(--bg-soft, #f5f6f7); }
.strength-opt input[type="radio"] { margin: 0; }
.strength-opt:has(input:checked) {
  background: rgba(40, 100, 200, 0.10);
  border-color: var(--brand-secondary, #2864c8);
  color: var(--brand-secondary, #2864c8);
}

.goal-net-header {
  font-size: 12px;
  color: var(--text-dim);
  margin-bottom: 4px;
  text-transform: uppercase;
  letter-spacing: 0.5px;
}
.goal-net-target {
  position: relative;
  margin-top: 6px;
  border: 1px solid var(--border, #d4d7dc);
  border-radius: var(--r-md, 8px);
  background: #fff;
  cursor: crosshair;
  overflow: hidden;
  line-height: 0;
}
.goal-net-target #goal-net-image {
  display: block;
  width: 100%;
  height: auto;
  background: #fff;
  user-select: none;
  -webkit-user-drag: none;
}
.goal-net-grid {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  pointer-events: none;
  z-index: 1;
}
.goal-net-grid line {
  stroke: rgba(255, 255, 255, 0.55);
  stroke-width: 0.5;
  stroke-dasharray: 2 2;
}
.goal-net-marker {
  position: absolute;
  display: none;            /* hidden until JS adds `.placed` */
  width: 28px;
  height: 28px;
  margin-left: -14px;
  margin-top: -14px;
  background: #111;
  border: 3px solid #fff;
  border-radius: 50%;
  box-shadow: 0 3px 8px rgba(0, 0, 0, 0.45);
  pointer-events: none;     /* clicks pass through to the image */
  z-index: 2;
}
.goal-net-marker.placed { display: block; }
.goal-net-zone-label {
  margin-top: 8px;
  font-size: 13px;
  font-weight: 600;
  color: var(--text);
  min-height: 18px;
}
.goal-net-zone-label:empty::before {
  content: "Click the net to mark a zone";
  color: var(--text-dim);
  font-weight: 400;
  font-style: italic;
}
.goal-net-clear {
  position: absolute;
  top: 6px; right: 6px;
  font-size: 11px;
  padding: 3px 8px;
  border: 1px solid var(--border, #d4d7dc);
  background: #fff;
  border-radius: var(--r, 6px);
  cursor: pointer;
  font-weight: 500;
  line-height: 1.2;
}
.goal-net-clear:hover { background: var(--bg-soft, #f5f6f7); }

/* ============================================================
   Game Center modal (Schedule → Game Center)
   ============================================================ */
.gc-topbar {
  display: grid;
  grid-template-columns: 1fr auto 1fr;
  align-items: center;
  gap: 12px;
  padding: 12px 20px;
  border-bottom: 1px solid var(--border-soft, #e6e8eb);
  position: sticky;
  top: 0;
  background: #fff;
  z-index: 2;
}
.gc-topbar h3 { font-size: 18px; font-weight: 700; letter-spacing: -0.01em; }
.gc-topbar > div:last-child { justify-self: end; }
#game-center-body { padding: 24px; }

/* Header */
.gc-header {
  display: grid;
  grid-template-columns: 1fr auto 1fr;
  align-items: center;
  gap: 24px;
  padding: 20px 24px;
  border-radius: var(--r-lg, 12px);
  background:
    linear-gradient(to right, color-mix(in srgb, var(--brand-primary) 8%, transparent), transparent 35%, transparent 65%, color-mix(in srgb, var(--brand-secondary) 8%, transparent));
  border: 1px solid var(--border-soft, #e6e8eb);
  margin-bottom: 24px;
}
.gc-team-name {
  font-size: 18px;
  font-weight: 700;
  letter-spacing: -0.005em;
}
.gc-team-left  { text-align: left; }
.gc-team-right { text-align: right; }
.gc-score-block { text-align: center; }
.gc-score-line {
  display: inline-flex;
  align-items: baseline;
  gap: 16px;
  font-size: 40px;
  font-weight: 700;
  letter-spacing: -0.02em;
  line-height: 1;
}
.gc-score-dash {
  font-size: 24px;
  font-weight: 400;
  color: var(--text-dim);
  position: relative;
  top: -4px;
}
.gc-meta {
  margin-top: 8px;
  font-size: 12px;
  color: var(--text-dim);
  letter-spacing: 0.2px;
}

/* Sections */
.gc-section { margin-bottom: 28px; }
.gc-section-title {
  font-size: 13px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 1px;
  color: var(--text-dim);
  margin: 0 0 12px 0;
}
.gc-empty {
  padding: 16px;
  background: var(--bg-soft, #f5f6f7);
  border-radius: var(--r-md, 8px);
  color: var(--text-dim);
  font-size: 13px;
}

/* Scoring Summary */
.gc-period { margin-bottom: 12px; }
.gc-period-title {
  font-size: 13px;
  font-weight: 700;
  margin: 0 0 8px 0;
}
.gc-goal-row {
  display: grid;
  grid-template-columns: 60px 1fr auto;
  align-items: center;
  gap: 12px;
  padding: 10px 12px 10px 16px;
  margin-bottom: 8px;
  background: #fff;
  border: 1px solid var(--border-soft, #e6e8eb);
  border-left: 4px solid var(--accent, var(--red));
  border-radius: var(--r-md, 8px);
  box-shadow: var(--shadow-xs, none);
}
.gc-goal-time { font-weight: 600; color: var(--text-dim); font-variant-numeric: tabular-nums; }
.gc-goal-title { display: flex; gap: 8px; align-items: center; flex-wrap: wrap; font-weight: 600; }
.gc-scorer { font-weight: 700; }
.gc-shot-type { color: var(--text-dim); font-weight: 500; font-size: 12px; }
.gc-assists { font-size: 12px; color: var(--text-dim); margin-top: 2px; }
.gc-goal-score {
  font-weight: 700;
  font-size: 16px;
  font-variant-numeric: tabular-nums;
  letter-spacing: -0.01em;
  min-width: 50px;
  text-align: right;
}
.gc-strength {
  display: inline-block;
  padding: 1px 6px;
  font-size: 10px;
  font-weight: 700;
  letter-spacing: 0.5px;
  border-radius: var(--r-pill, 999px);
  background: var(--bg-soft);
  color: var(--text-dim);
}
.gc-strength-pp { background: rgba(40, 100, 200, 0.14); color: var(--blue); }
.gc-strength-sh { background: rgba(124, 92, 255, 0.14); color: var(--red); }
.gc-strength-en { background: rgba(31, 158, 90, 0.14); color: var(--green); }

/* Team Stats */
.gc-stats-head {
  display: grid;
  grid-template-columns: 1fr 1fr 1fr;
  align-items: center;
  margin-bottom: 12px;
}
.gc-stats-team {
  font-size: 14px;
  font-weight: 700;
  letter-spacing: -0.005em;
}
.gc-stats-team-left { text-align: left; }
.gc-stats-team-right { text-align: right; }
.gc-stat-row {
  display: grid;
  grid-template-columns: 60px 1fr 60px;
  align-items: center;
  padding: 8px 0 4px;
}
.gc-stat-num {
  font-size: 20px;
  font-weight: 700;
  font-variant-numeric: tabular-nums;
}
.gc-stat-num-left { text-align: left; }
.gc-stat-num-right { text-align: right; }
.gc-stat-label {
  text-align: center;
  text-transform: uppercase;
  font-size: 11px;
  letter-spacing: 0.6px;
  color: var(--text-dim);
  font-weight: 600;
}
.gc-bar-row {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 8px;
  padding: 0 0 10px;
  border-bottom: 1px solid var(--border-soft, #e6e8eb);
  margin-bottom: 4px;
}
.gc-bar {
  height: 4px;
  border-radius: var(--r-pill, 999px);
}
.gc-bar-left  { background: var(--brand-primary, var(--red));   margin-left: auto; }
.gc-bar-right { background: var(--brand-secondary, var(--blue)); margin-right: auto; }

@media (max-width: 640px) {
  .gc-header { grid-template-columns: 1fr; gap: 8px; text-align: center; }
  .gc-team-left, .gc-team-right { text-align: center; }
  .gc-goal-row { grid-template-columns: 50px 1fr auto; gap: 8px; }
}

/* Game Center — Player Stats section */
.gc-section-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  margin-bottom: 8px;
}
.gc-section-head .gc-section-title { margin: 0; }
.gc-player-table { font-size: 13px; }
.gc-player-table .gc-dim { color: var(--text-dim); }
.gc-stats-hint {
  margin-top: 6px;
  font-size: 11px;
  color: var(--text-dim);
}

/* ============================================================
   Game Center — rich header, logos, highlights row
   ============================================================ */
.gc-header-rich {
  display: grid;
  grid-template-columns: 1fr auto 1fr;
  align-items: center;
  gap: 24px;
  padding: 24px;
  border-radius: var(--r-lg, 12px);
  background:
    linear-gradient(135deg, color-mix(in srgb, var(--brand-primary) 14%, transparent), transparent 50%),
    linear-gradient(225deg, color-mix(in srgb, var(--brand-secondary) 14%, transparent), transparent 50%),
    #fff;
  border: 1px solid var(--border-soft, #e6e8eb);
  margin-bottom: 12px;
}
.gc-side { display: flex; align-items: center; gap: 16px; }
.gc-side-us  { justify-content: flex-start; }
.gc-side-opp { justify-content: flex-end; }
.gc-side-info { flex: 1; min-width: 0; }
.gc-side-opp .gc-side-info { text-align: right; }
.gc-side-name {
  font-size: 18px; font-weight: 700; letter-spacing: -0.01em;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.gc-side-sub {
  margin-top: 2px;
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.6px;
  text-transform: uppercase;
  color: var(--text-dim);
}
.gc-side-score {
  font-size: 52px;
  font-weight: 800;
  font-variant-numeric: tabular-nums;
  letter-spacing: -0.03em;
  line-height: 1;
  min-width: 64px;
  text-align: center;
}
.gc-side-score-us  { color: var(--brand-primary, var(--red)); }
.gc-side-score-opp { color: var(--brand-secondary, var(--blue)); }

.gc-logo {
  width: 56px; height: 56px;
  object-fit: contain;
  border-radius: var(--r-md, 8px);
  background: #fff;
  padding: 2px;
  box-shadow: var(--shadow-xs, 0 1px 2px rgba(0,0,0,.06));
}
.gc-logo-placeholder {
  display: grid; place-items: center;
  color: #fff;
  font-weight: 800;
  font-size: 22px;
  letter-spacing: -0.01em;
}
.gc-logo-us  { background: var(--brand-primary,   var(--red)); }
.gc-logo-opp { background: var(--brand-secondary, var(--blue)); }

.gc-divider {
  text-align: center;
  display: flex; flex-direction: column; align-items: center; gap: 4px;
}
.gc-divider-status {
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 1px;
  color: var(--text-dim);
}
.gc-divider-date {
  font-size: 12px;
  color: var(--text);
}

/* Highlights row — sits right under the header, compact key stats per team. */
.gc-highlights {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 12px;
  margin-bottom: 24px;
}
.gc-highlight {
  padding: 10px 16px;
  border-radius: var(--r-md, 8px);
  font-size: 13px;
  font-weight: 600;
  color: var(--text);
  display: flex;
  gap: 6px;
  align-items: center;
}
.gc-highlight-us  { background: color-mix(in srgb, var(--brand-primary)   12%, #fff); text-align: left;  }
.gc-highlight-opp { background: color-mix(in srgb, var(--brand-secondary) 12%, #fff); text-align: right; justify-content: flex-end; }
.gc-highlight-num { font-size: 18px; font-weight: 800; font-variant-numeric: tabular-nums; }
.gc-highlight-us  .gc-highlight-num { color: var(--brand-primary, var(--red)); }
.gc-highlight-opp .gc-highlight-num { color: var(--brand-secondary, var(--blue)); }
.gc-highlight-sep { color: var(--text-dim); margin: 0 4px; }

/* Mini logo (24px) — used on scoring rows + team-stats header. */
.gc-mini-logo {
  width: 24px; height: 24px;
  flex: 0 0 auto;
  object-fit: contain;
  border-radius: var(--r-sm, 4px);
  background: #fff;
}
.gc-mini-logo-placeholder {
  display: grid; place-items: center;
  color: #fff;
  font-weight: 800;
  font-size: 12px;
  letter-spacing: -0.01em;
}
.gc-mini-us  { background: var(--brand-primary,   var(--red)); }
.gc-mini-opp { background: var(--brand-secondary, var(--blue)); }

/* Scoring rows — add a badge column and tint the background subtly per team. */
.gc-goal-row {
  display: grid;
  grid-template-columns: 56px 28px 1fr auto;
  align-items: center;
  gap: 12px;
  padding: 10px 12px 10px 14px;
  margin-bottom: 8px;
  background: #fff;
  border: 1px solid var(--border-soft, #e6e8eb);
  border-left: 4px solid var(--brand-primary, var(--red));
  border-radius: var(--r-md, 8px);
  box-shadow: var(--shadow-xs, none);
}
.gc-goal-us  { border-left-color: var(--brand-primary,   var(--red));  background: linear-gradient(90deg, color-mix(in srgb, var(--brand-primary)   5%, #fff), #fff 50%); }
.gc-goal-opp { border-left-color: var(--brand-secondary, var(--blue)); background: linear-gradient(90deg, color-mix(in srgb, var(--brand-secondary) 5%, #fff), #fff 50%); }

/* Team stats header — team labels with logos flanking the comparison. */
.gc-stats-team { display: flex; align-items: center; gap: 8px; }
.gc-stats-team-left  { justify-content: flex-start; }
.gc-stats-team-right { justify-content: flex-end; }

/* Mobile — let the header stack cleanly. */
@media (max-width: 700px) {
  .gc-header-rich { grid-template-columns: 1fr; }
  .gc-side, .gc-side-opp { flex-wrap: wrap; }
  .gc-side-score { font-size: 40px; }
  .gc-highlights { grid-template-columns: 1fr; }
  .gc-highlight-opp { text-align: left; justify-content: flex-start; }
}

/* Team-menu — association grouping with collapsible headers. */
.team-menu-group {
  border-top: 1px solid var(--border-soft, rgba(255,255,255,.06));
  margin-top: 4px;
  padding-top: 4px;
}
.team-menu-group:first-of-type { border-top: none; margin-top: 0; padding-top: 0; }
.team-menu-group-head {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 8px 12px;
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.6px;
  text-transform: uppercase;
  color: var(--text-dim, #6b7280);
  cursor: pointer;
  user-select: none;
}
.team-menu-group-head:hover { background: rgba(255,255,255,.04); }
.team-menu-group-head .chev { transition: transform .15s var(--ease, ease); }
.team-menu-group.collapsed .chev { transform: rotate(-90deg); }
.team-menu-group-count {
  margin-left: auto;
  font-weight: 600;
  font-variant-numeric: tabular-nums;
}
.team-menu-group-body {
  overflow: hidden;
  max-height: 999px;
  transition: max-height .2s var(--ease, ease);
}
.team-menu-group.collapsed .team-menu-group-body { max-height: 0; }
.team-menu-group-body .item { padding-left: 28px; }

/* ============================================================
   Practice plan clipboards
   Each plan-card is styled to look like a coach's wall clipboard:
   team-color frame, metal clip at the top, line-ruled drill list.
   ============================================================ */
#plan-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
  gap: 44px 24px;
  align-items: stretch;
  padding-top: 38px; /* leave room for the clip + lever bump that pokes above the card */
  overflow: visible;
}

/* Override the generic .card look just for plan-cards. */
.plan-card {
  position: relative;
  background: #fff;
  border: 5px solid var(--brand-primary, var(--red));
  border-radius: 6px;
  padding: 22px 18px 16px;
  margin: 0;
  box-shadow: 0 6px 16px -8px rgba(0,0,0,.18), 0 2px 4px -2px rgba(0,0,0,.08);
  display: flex; flex-direction: column;
  min-height: 320px;
  transition: transform var(--t-fast, 120ms) var(--ease, ease), box-shadow var(--t, 180ms) var(--ease, ease);
}
.plan-card:hover {
  transform: translateY(-2px);
  box-shadow: 0 14px 30px -10px rgba(0,0,0,.22), 0 4px 10px -4px rgba(0,0,0,.10);
}

/* The metal clip at the top of the clipboard. */
.plan-card::before {
  content: "";
  position: absolute;
  top: -14px;
  left: 50%;
  transform: translateX(-50%);
  width: 78px;
  height: 24px;
  border-radius: 4px 4px 3px 3px;
  background:
    linear-gradient(180deg, #f4f5f7 0%, #cdd2d8 38%, #a9aeb6 70%, #c4c9d0 100%);
  border: 1px solid #8b9099;
  box-shadow: 0 2px 4px rgba(0,0,0,.15);
}
/* Tiny lever bump on top of the clip. */
.plan-card::after {
  content: "";
  position: absolute;
  top: -22px;
  left: 50%;
  transform: translateX(-50%);
  width: 26px;
  height: 10px;
  border-radius: 2px 2px 1px 1px;
  background: linear-gradient(180deg, #e8eaed 0%, #b7bcc4 100%);
  border: 1px solid #8b9099;
  border-bottom: none;
}

/* Header inside the clipboard: plan name + actions. Header text is centered
   to match how a real clipboard label sits at the top. Icons float to the
   right corner via absolute positioning so they don't push the title off
   center. */
.plan-card .card-head {
  position: relative;
  margin-bottom: 12px;
  padding-bottom: 10px;
  border-bottom: 2px solid var(--brand-primary, var(--red));
  display: block;        /* drop the flex layout from .card .card-head */
  text-align: center;
}
.plan-card-head-info { padding: 0 56px; }   /* leave room for the two icons */
.plan-card h2 {
  font-size: 17px;
  font-weight: 800;
  text-transform: uppercase;
  letter-spacing: 0.4px;
  color: var(--brand-primary, var(--red));
  line-height: 1.2;
  margin: 0;
}
.plan-card .card-head .sub {
  margin-top: 4px;
  font-size: 11px;
  color: var(--text-dim);
  font-weight: 500;
  letter-spacing: 0.3px;
}
.plan-card-head-actions {
  position: absolute;
  top: 0;
  right: 0;
  display: flex;
  gap: 2px;
}
.btn-icon {
  background: transparent;
  border: none;
  width: 28px; height: 28px;
  display: inline-flex; align-items: center; justify-content: center;
  border-radius: var(--r-sm, 4px);
  color: var(--text-dim);
  cursor: pointer;
  padding: 0;
  transition: background var(--t-fast, 120ms) var(--ease, ease), color var(--t-fast, 120ms) var(--ease, ease);
}
.btn-icon:hover { background: color-mix(in srgb, var(--brand-primary, var(--red)) 8%, transparent); color: var(--text); }
.btn-icon.del:hover { background: color-mix(in srgb, var(--red) 10%, transparent); color: var(--red); }
.btn-icon .icon-inline { width: 16px; height: 16px; }

/* Body: drill list as ruled lines. */
.plan-card .plan-body {
  flex: 1;
  display: flex;
  flex-direction: column;
}
.plan-card .plan-drill {
  display: grid;
  grid-template-columns: 26px 1fr auto auto;
  gap: 8px;
  align-items: center;
  padding: 7px 2px;
  font-size: 13px;
  border-bottom: 1px dashed color-mix(in srgb, var(--brand-primary, var(--red)) 22%, transparent);
}
.plan-card .plan-drill:last-of-type { border-bottom: 1px dashed color-mix(in srgb, var(--brand-primary, var(--red)) 22%, transparent); }
.plan-card .plan-drill .idx {
  width: 22px; height: 22px;
  border-radius: 50%;
  display: grid; place-items: center;
  background: var(--brand-primary, var(--red));
  color: #fff;
  font-weight: 700;
  font-size: 11px;
  font-variant-numeric: tabular-nums;
}
.plan-card .plan-drill .nm { font-weight: 600; line-height: 1.3; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.plan-card .plan-drill .mins {
  font-size: 11px;
  font-weight: 700;
  color: var(--text-dim);
  font-variant-numeric: tabular-nums;
  padding: 2px 6px;
  border-radius: var(--r-pill, 999px);
  background: color-mix(in srgb, var(--brand-primary, var(--red)) 8%, transparent);
}
.plan-card .plan-drill .rm {
  background: transparent;
  border: none;
  padding: 4px;
  color: var(--text-dim);
  cursor: pointer;
  border-radius: var(--r-sm, 4px);
}
.plan-card .plan-drill .rm:hover { background: color-mix(in srgb, var(--red) 10%, transparent); color: var(--red); }

/* Footer actions inside the clipboard, pushed to the bottom. */
.plan-card .plan-actions {
  display: flex;
  gap: 6px;
  flex-wrap: wrap;
  margin-top: auto;
  padding-top: 14px;
}
.plan-card .plan-actions .btn {
  padding: 6px 10px;
  font-size: 12px;
  flex: 1;
}
.plan-card .plan-actions .btn-primary {
  flex: 1.5;
  background: var(--brand-primary, var(--red));
  border-color: var(--brand-primary, var(--red));
  /* Force white on text + icon — the old ▶ glyph rendered as a colored emoji
     against the red, which read as "black text on red". */
  color: #fff !important;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
}
.plan-card .plan-actions .btn-primary .icon-inline { color: #fff; width: 13px; height: 13px; }

@media (max-width: 600px) {
  #plan-list { grid-template-columns: 1fr; gap: 32px; }
  .plan-card { min-height: 0; }
}

/* ============================================================
   Practice Plans — inline editor + tab strip
   ============================================================ */
/* Plan tabs follow the same Chrome-style design as the drill page's
   .drill-tab tabs — grey when inactive, white when active, top-rounded so
   they appear to sit on the page below. Sits inside the dark edit-bar. */
.plan-tab-strip {
  display: flex;
  align-items: stretch;
  gap: 2px;
  flex: 0 0 auto;
}
.plan-tab {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 0 10px 0 12px;
  background: #d4d7dc;
  color: #3a3f46;
  border-radius: 6px 6px 0 0;
  font-size: 12.5px;
  font-weight: 500;
  white-space: nowrap;
  cursor: pointer;
  height: 30px;
  margin-top: 4px;
  border: 1px solid transparent;
  border-bottom: none;
  max-width: 200px;
  user-select: none;
}
.plan-tab:hover { background: #c8ccd1; }
.plan-tab.active {
  background: #ffffff;
  color: #111;
  border-color: #c9ccd1;
}
.plan-tab-name {
  overflow: hidden;
  text-overflow: ellipsis;
  max-width: 160px;
}
.plan-tab-close {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 18px; height: 18px;
  padding: 0;
  margin-right: -4px;
  border: none;
  background: transparent;
  border-radius: 50%;
  color: inherit;
  font-size: 16px;
  line-height: 1;
  cursor: pointer;
  opacity: 0.7;
}
.plan-tab-close:hover {
  background: rgba(0,0,0,0.1);
  opacity: 1;
}

/* Inline editor surface. Matches the page width and uses team color for the
   active accents but doesn't try to LOOK like a clipboard — the clipboard
   metaphor stays in the list grid. */
.plan-editor {
  background: #fff;
  border: 1px solid var(--border-soft, #e6e8eb);
  border-top: 4px solid var(--brand-primary, var(--red));
  border-radius: var(--r-md, 8px);
  padding: 22px 24px;
  margin-bottom: 24px;
  box-shadow: var(--shadow-sm);
}
.plan-editor-head {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 200px 180px;
  gap: 12px;
  margin-bottom: 14px;
}
.plan-editor-book {
  font-size: 13px !important;
  color: var(--text-dim);
  border: 1px solid var(--border) !important;
  border-radius: var(--r, 6px) !important;
  padding: 6px 10px !important;
}
.plan-editor-book:focus { color: var(--text); }
.plan-editor-name {
  font-size: 22px !important;
  font-weight: 700 !important;
  border: none !important;
  border-bottom: 2px solid transparent !important;
  border-radius: 0 !important;
  padding: 4px 0 !important;
  background: transparent !important;
  letter-spacing: -0.01em;
}
.plan-editor-name:focus { border-bottom-color: var(--brand-primary, var(--red)) !important; outline: none !important; box-shadow: none !important; }
.plan-editor-date {
  font-size: 13px !important;
  text-align: right;
  color: var(--text-dim);
  border: 1px solid var(--border) !important;
  border-radius: var(--r, 6px) !important;
  padding: 6px 10px !important;
}
.plan-editor-notes-label,
.plan-editor-drill-head h3 {
  display: block;
  font-size: 11px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 1px;
  color: var(--text-dim);
  margin: 0 0 6px 0;
}
.plan-editor-notes {
  width: 100%;
  border: 1px solid var(--border, #d8dce1);
  border-radius: var(--r, 6px);
  padding: 10px 12px;
  font-family: inherit;
  font-size: 14px;
  min-height: 70px;
  margin-bottom: 0;
  resize: vertical;
}

/* Notes block — collapsed by default to save vertical space; click the
   header row to expand. The header shows a chevron, the "Notes" label, and
   a short preview of the existing notes (or placeholder if empty). */
.plan-editor-notes-block { margin: 4px 0 18px; }
.plan-editor-notes-toggle {
  display: flex;
  align-items: center;
  gap: 8px;
  width: 100%;
  padding: 6px 0;
  background: transparent;
  border: 0;
  cursor: pointer;
  text-align: left;
  font-family: inherit;
}
.plan-editor-notes-chev {
  width: 14px; height: 14px;
  color: var(--text-dim);
  flex-shrink: 0;
  transition: transform var(--t-fast, 120ms) var(--ease, ease);
}
.plan-editor-notes-block:not(.is-collapsed) .plan-editor-notes-chev { transform: rotate(90deg); }
.plan-editor-notes-toggle .plan-editor-notes-label { margin: 0; }
.plan-editor-notes-preview {
  flex: 1;
  font-size: 12px;
  color: var(--text-dim);
  font-weight: 400;
  font-style: italic;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  min-width: 0;
  letter-spacing: 0;
  text-transform: none;
}
.plan-editor-notes-preview.is-empty::before {
  content: 'Add notes for this plan…';
  opacity: 0.6;
}
.plan-editor-notes-block .plan-editor-notes { margin-top: 6px; }
.plan-editor-notes-block.is-collapsed .plan-editor-notes { display: none; }
.plan-editor-drill-head {
  display: flex;
  align-items: center;
  gap: 10px;
  margin-bottom: 8px;
}
.plan-editor-drill-head h3 { margin-right: 4px; }
.plan-editor-summary {
  font-size: 12px;
  color: var(--text-dim);
  font-weight: 500;
  margin-left: auto;
}

/* Toggle next to the Drills heading — collapses or expands every drill block
   in the active plan in one click. */
.plan-editor-collapse-all {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 4px 10px 4px 8px;
  background: transparent;
  border: 1px solid var(--border, #d8dce1);
  border-radius: var(--r-pill, 999px);
  color: var(--text-dim);
  font-size: 11.5px;
  font-weight: 600;
  letter-spacing: 0.2px;
  cursor: pointer;
  transition: background var(--t-fast, 120ms) var(--ease, ease), color var(--t-fast, 120ms) var(--ease, ease), border-color var(--t-fast, 120ms) var(--ease, ease);
}
.plan-editor-collapse-all svg {
  width: 14px;
  height: 14px;
  transition: transform var(--t-fast, 120ms) var(--ease, ease);
}
.plan-editor-collapse-all[data-state="collapsed"] svg { transform: rotate(180deg); }
.plan-editor-collapse-all:hover {
  background: color-mix(in srgb, var(--brand-primary, var(--red)) 8%, transparent);
  border-color: var(--brand-primary, var(--red));
  color: var(--brand-primary, var(--red));
}
.plan-editor-collapse-all:focus-visible {
  outline: 2px solid var(--brand-primary, var(--red));
  outline-offset: 2px;
}
.plan-editor-notes-layout svg { transform: none !important; }

/* Notes-below layout (Ian: "show me an option where the notes are
   below"): drill art full width with the description underneath,
   instead of the side-by-side columns. No height cap / Read more —
   the notes just flow. */
.plan-editor-drill-list.ped-notes-below .ped-block-body { grid-template-columns: 1fr; }
.plan-editor-drill-list.ped-notes-below .ped-block-body .ped-thumb-btn {
  max-width: 660px;
  /* Left-aligned, not centered (Ian: "its all centered on desktop"). */
  margin: 0;
}
.plan-editor-drill-list.ped-notes-below .ped-desc { max-height: none !important; }
.plan-editor-drill-list.ped-notes-below .ped-desc.is-overflow {
  -webkit-mask-image: none;
  mask-image: none;
}
.plan-editor-drill-list.ped-notes-below .ped-read-more { display: none; }

/* Inline drill-notes editing inside a plan block. */
.ped-desc.is-editing {
  border: 1.5px solid var(--brand-primary, var(--red));
  border-radius: 8px;
  padding: 8px 10px;
  background: #fff;
  min-height: 44px;
  max-height: none !important;
  overflow: visible;
  outline: none;
  -webkit-mask-image: none !important;
  mask-image: none !important;
}
.ped-block-icon.is-editing-desc {
  background: var(--brand-primary, var(--red));
  color: #fff;
}

/* Motion drills cycle their frames every 3s — badge on the art. */
.ped-block-body .ped-thumb-btn { position: relative; }
.ped-motion-badge {
  position: absolute;
  left: 8px;
  bottom: 8px;
  display: inline-flex;
  align-items: center;
  gap: 3px;
  padding: 2px 8px;
  border-radius: 999px;
  background: rgba(16, 19, 24, 0.78);
  color: #fff;
  font-size: 10.5px;
  font-weight: 700;
  letter-spacing: 0.4px;
  pointer-events: none;
  font-variant-numeric: tabular-nums;
}
.plan-editor-drill-list {
  display: flex;
  flex-direction: column;
  gap: 6px;
  margin-bottom: 12px;
}
/* Legacy single-row layout (kept around in case any older view references it).
   Real drill rows now use .ped-block below. */
.ped-row {
  display: grid;
  grid-template-columns: 32px 250px minmax(0, 1fr) auto auto;
  gap: 14px;
  align-items: center;
  padding: 10px 12px;
  background: var(--bg-soft, #f5f6f7);
  border-radius: var(--r, 6px);
  border: 1px solid transparent;
  transition: border-color var(--t-fast) var(--ease);
}
.ped-row:hover { border-color: var(--border, #d8dce1); }

/* New drill block — heading bar at the top (drag handle + title + actions),
   collapsible body below (thumb + description). Background uses the team's
   secondary brand color at low opacity so each block reads as its own card. */
.ped-block {
  border-radius: var(--r-md, 8px);
  border: 1px solid color-mix(in srgb, var(--brand-secondary, #2864c8) 18%, var(--border-soft, #e6e8eb));
  background: color-mix(in srgb, var(--brand-secondary, #2864c8) 7%, #fff);
  overflow: hidden;
  transition: box-shadow var(--t-fast, 120ms) var(--ease, ease), opacity var(--t-fast, 120ms) var(--ease, ease), border-color var(--t-fast, 120ms) var(--ease, ease);
}
.ped-block + .ped-block { margin-top: 8px; }
.ped-block.is-dragging { opacity: 0.45; }
.ped-block.drop-above  { box-shadow: 0 -3px 0 0 var(--brand-primary, var(--red)); }
.ped-block.drop-below  { box-shadow:  0  3px 0 0 var(--brand-primary, var(--red)); }

.ped-block-head {
  display: grid;
  /* handle · idx · title · mins · chevron · edit-notes · expand · remove
     (the edit-notes pencil added a column — with only 7 the remove X
     wrapped onto an implicit second row) */
  grid-template-columns: 28px 32px minmax(0, 1fr) auto auto auto auto auto;
  gap: 10px;
  align-items: center;
  padding: 8px 12px;
  /* Primary brand color so each drill block reads as a distinct, branded
     section. Index badge, title, and icons go white. */
  background: var(--brand-primary, var(--red));
  color: #fff;
  border-bottom: 1px solid color-mix(in srgb, #000 18%, var(--brand-primary, var(--red)));
  cursor: grab;
  user-select: none;
}
.ped-block-head:active { cursor: grabbing; }
.ped-block.is-collapsed .ped-block-head { border-bottom-color: transparent; }
/* Index badge sits inside the heading now — flip it to white-on-transparent
   so it reads on the dark primary background. */
.ped-block-head .ped-idx {
  background: rgba(255,255,255,0.18);
  color: #fff;
}

.ped-drag-handle {
  display: inline-grid; place-items: center;
  width: 22px; height: 22px;
  color: rgba(255,255,255,0.75);
  cursor: grab;
}
.ped-drag-handle svg { width: 18px; height: 18px; }
.ped-drag-handle:hover { color: #fff; }
.ped-block-head:active .ped-drag-handle { cursor: grabbing; }

.ped-block-title {
  font-weight: 700;
  font-size: 14px;
  color: #fff;
  letter-spacing: 0.2px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* Collapse chevron — points up by default, rotates when collapsed. */
.ped-block-collapse {
  width: 28px; height: 28px;
  display: inline-grid; place-items: center;
  padding: 0; margin: 0;
  background: transparent;
  border: 0;
  border-radius: var(--r-sm, 4px);
  color: rgba(255,255,255,0.8);
  cursor: pointer;
  transition: background var(--t-fast, 120ms) var(--ease, ease), color var(--t-fast, 120ms) var(--ease, ease);
}
.ped-block-collapse svg { width: 16px; height: 16px; transition: transform var(--t-fast, 120ms) var(--ease, ease); }
.ped-block.is-collapsed .ped-block-collapse svg { transform: rotate(180deg); }
.ped-block-collapse:hover { background: rgba(255,255,255,0.14); color: #fff; }

/* Generic icon button for expand/remove in the heading. */
.ped-block-icon {
  width: 28px; height: 28px;
  display: inline-grid; place-items: center;
  padding: 0; margin: 0;
  background: transparent;
  border: 0;
  border-radius: var(--r-sm, 4px);
  color: rgba(255,255,255,0.8);
  cursor: pointer;
  transition: background var(--t-fast, 120ms) var(--ease, ease), color var(--t-fast, 120ms) var(--ease, ease);
}
.ped-block-icon svg { width: 15px; height: 15px; }
.ped-block-icon:hover { background: rgba(255,255,255,0.14); color: #fff; }
.ped-block-icon-danger:hover { background: rgba(255,255,255,0.22); color: #fff; }

/* The plan-number badge label inside the dark heading needs no extra tint. */
.ped-mins {
  /* When a drill row's mins pill sits in the dark heading, flip its colors so
     it pops on the brand-color background instead of disappearing into it. */
}
.ped-block-head .ped-mins {
  background: rgba(255,255,255,0.22);
  color: #fff;
}

/* Body: thumb + description side by side. Collapsible.
   Thumb takes ~55% of the body width; description gets the rest. */
.ped-block-body {
  display: grid;
  grid-template-columns: 360px 1fr;
  gap: 14px;
  align-items: start;
  padding: 12px;
}
.ped-block.is-collapsed .ped-block-body { display: none; }
/* No-thumb drills (quick-add stubs) collapse to a single column so the notes
   sit flush with the left edge of the body — no empty thumbnail gutter. */
.ped-block.no-thumb .ped-block-body { grid-template-columns: 1fr; }
.ped-block-body .ped-thumb,
.ped-block-body .ped-thumb-btn { background: transparent; }
.ped-block-body .ped-info {
  padding-top: 4px;
  min-width: 0;
  display: flex;
  flex-direction: column;
}
.ped-desc-empty { font-style: italic; opacity: 0.7; }

@media (max-width: 720px) {
  .ped-block-body { grid-template-columns: 1fr; }
}

/* Responsive thumb — fills its grid column. Aspect-ratio matches the old
   250×150 box (5:3) so the rink letterboxes the same as before regardless of
   how wide the editor canvas is. */
.ped-block-body .ped-thumb,
.ped-block-body .ped-thumb-btn,
.ped-block-body .ped-thumb-placeholder {
  width: 100%;
  height: auto;
  aspect-ratio: 5 / 3;
  max-width: none;
}
.ped-block-body .ped-thumb { object-fit: contain; }

/* Description preserves rich-text formatting from the drill notes editor
   (lists, bold, inline icons). Capped to the thumb's rendered height via JS;
   a fade mask + Read more button reveal the rest when it overflows. */
.ped-desc {
  font-size: 13px;
  line-height: 1.5;
  color: var(--text);
  overflow: hidden;
  position: relative;
}
.ped-desc p { margin: 0 0 6px; }
.ped-desc p:last-child { margin-bottom: 0; }
.ped-desc ul,
.ped-desc ol { margin: 4px 0 6px; padding-left: 22px; }
.ped-desc ul { list-style: disc outside; }
.ped-desc ol { list-style: decimal outside; }
.ped-desc li { margin: 1px 0; }
.ped-desc li::marker { color: var(--text-dim); }
.ped-desc h1,
.ped-desc h2,
.ped-desc h3 { font-size: 14px; font-weight: 700; margin: 6px 0 4px; }
.ped-desc img.inline-icon {
  height: 1.1em;
  width: auto;
  vertical-align: -2px;
  margin: 0 2px;
}
/* Fade-out at the bottom when truncated (but not when expanded). */
.ped-desc.is-overflow:not(.is-expanded) {
  -webkit-mask-image: linear-gradient(to bottom, #000 70%, transparent 100%);
          mask-image: linear-gradient(to bottom, #000 70%, transparent 100%);
}

.ped-read-more {
  align-self: flex-start;
  margin-top: 4px;
  background: transparent;
  border: 0;
  padding: 3px 0;
  font-size: 12px;
  font-weight: 700;
  color: var(--brand-primary, var(--red));
  cursor: pointer;
  border-bottom: 1px solid transparent;
  transition: border-color var(--t-fast, 120ms) var(--ease, ease), color var(--t-fast, 120ms) var(--ease, ease);
}
.ped-read-more:hover { border-bottom-color: currentColor; }
.ped-read-more[hidden] { display: none; }
.ped-idx {
  width: 26px; height: 26px;
  display: grid; place-items: center;
  border-radius: 50%;
  background: var(--brand-primary, var(--red));
  color: #fff;
  font-weight: 700;
  font-size: 12px;
  font-variant-numeric: tabular-nums;
}
.ped-thumb {
  width: 250px; height: 150px;
  /* `contain` so the entire rink shows — no cropping. Transparent letterbox
     blends with whatever the row's background is. */
  object-fit: contain;
  border-radius: var(--r-sm, 4px);
  background: transparent;
  border: 0;
}
.ped-thumb-placeholder { display: block; }
.ped-info {
  display: flex;
  flex-direction: column;
  gap: 4px;
  min-width: 0; /* let text truncate inside grid 1fr column */
}
.ped-name {
  font-weight: 700;
  font-size: 15px;
  line-height: 1.25;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  color: var(--text);
}
.ped-mins {
  font-size: 11px; font-weight: 700;
  padding: 2px 7px;
  border-radius: var(--r-pill, 999px);
  background: color-mix(in srgb, var(--brand-primary, var(--red)) 10%, transparent);
  color: var(--brand-primary, var(--red));
}
.ped-actions { display: inline-flex; gap: 2px; }
.ped-btn {
  width: 24px; height: 24px;
  border: 1px solid var(--border, #d8dce1);
  background: #fff;
  cursor: pointer;
  border-radius: var(--r-sm, 4px);
  font-size: 10px;
  color: var(--text-dim);
  display: inline-flex; align-items: center; justify-content: center;
  padding: 0;
}
.ped-btn:hover:not([disabled]) { color: var(--text); border-color: var(--text-dim); }
.ped-btn[disabled] { opacity: 0.4; cursor: not-allowed; }
.ped-rm:hover { color: var(--red); border-color: var(--red); }

.plan-editor-add-row {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 10px;
  margin: 6px 0 18px;
}
/* Outlined "card" style add button — icon on the left, title + subtitle stacked
   on the right. Primary variant uses the team's brand color for emphasis. */
.plan-add-btn {
  display: inline-flex;
  align-items: center;
  gap: 12px;
  width: 100%;
  padding: 12px 14px;
  background: #fff;
  border: 1.5px dashed var(--border, #d8dce1);
  border-radius: var(--r-md, 8px);
  color: var(--text);
  cursor: pointer;
  text-align: left;
  font-family: inherit;
  transition: border-color var(--t-fast, 120ms) var(--ease, ease), background var(--t-fast, 120ms) var(--ease, ease), transform var(--t-fast, 120ms) var(--ease, ease);
}
.plan-add-btn:hover {
  border-style: solid;
  border-color: var(--brand-primary, var(--red));
  background: color-mix(in srgb, var(--brand-primary, var(--red)) 5%, #fff);
  transform: translateY(-1px);
}
.plan-add-btn:focus-visible {
  outline: 2px solid var(--brand-primary, var(--red));
  outline-offset: 2px;
}
.plan-add-btn-icon {
  display: inline-grid; place-items: center;
  width: 36px; height: 36px;
  border-radius: var(--r-sm, 6px);
  background: color-mix(in srgb, var(--brand-primary, var(--red)) 10%, #fff);
  color: var(--brand-primary, var(--red));
  flex-shrink: 0;
}
.plan-add-btn-icon svg { width: 20px; height: 20px; }
.plan-add-btn-text {
  display: flex;
  flex-direction: column;
  gap: 1px;
  min-width: 0;
}
.plan-add-btn-title {
  font-weight: 700;
  font-size: 14px;
  line-height: 1.2;
}
.plan-add-btn-sub {
  font-size: 11.5px;
  color: var(--text-dim);
  line-height: 1.3;
}
/* Primary variant — slightly more saturated so the library option reads as
   the default action. */
.plan-add-btn-primary { border-style: solid; }
.plan-add-btn-primary .plan-add-btn-icon {
  background: var(--brand-primary, var(--red));
  color: #fff;
}

@media (max-width: 640px) {
  .plan-editor-add-row { grid-template-columns: 1fr; }
}

/* Attach-to-practice modal — list of practices the coach can link this plan to. */
.attach-practice-list {
  display: flex;
  flex-direction: column;
  gap: 6px;
  max-height: 360px;
  overflow-y: auto;
  margin: 0 0 12px;
}
.attach-practice-item {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  align-items: center;
  gap: 10px;
  padding: 10px 12px;
  border: 1px solid var(--border-soft, #e6e8eb);
  border-radius: var(--r-sm, 6px);
  background: #fff;
  cursor: pointer;
  transition: border-color var(--t-fast, 120ms) var(--ease, ease), background var(--t-fast, 120ms) var(--ease, ease);
}
.attach-practice-item:hover {
  border-color: var(--brand-primary, var(--red));
  background: color-mix(in srgb, var(--brand-primary, var(--red)) 6%, #fff);
}
.attach-practice-item.is-current {
  border-color: var(--brand-primary, var(--red));
  background: color-mix(in srgb, var(--brand-primary, var(--red)) 10%, #fff);
  cursor: default;
}
.attach-practice-main { min-width: 0; }
.attach-practice-title {
  font-weight: 700;
  font-size: 14px;
  color: var(--text);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.attach-practice-meta {
  font-size: 12px;
  color: var(--text-dim);
  margin-top: 2px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.attach-practice-current {
  font-size: 11px;
  color: var(--text-dim);
  margin-top: 4px;
}

/* Top action toolbar — visibility toggles on the left, action icon buttons
   on the right. Sits between the plan name/date row and the notes field. */
.plan-editor-toolbar {
  display: flex;
  gap: 16px;
  justify-content: space-between;
  align-items: center;
  flex-wrap: wrap;
  margin-bottom: 16px;
  padding: 10px 12px;
  background: var(--bg-soft, #f4f5f7);
  border-radius: var(--r-md, 8px);
}
.plan-editor-toolbar-left {
  display: flex;
  align-items: center;
  gap: 18px;
  flex-wrap: wrap;
}
.plan-editor-toolbar-right {
  display: flex;
  align-items: center;
  gap: 6px;
}
/* Compact toggles inside the toolbar (override the looser .plan-visibility-row
   spacing used elsewhere). */
.plan-editor-toolbar .plan-visibility-toggle { margin: 0; font-size: 12.5px; }

/* Icon-only action buttons in the toolbar. Square 36×36 tap target, ghost
   style by default. Browser-native `title` provides the hover tooltip. */
.plan-toolbar-icon-btn {
  width: 36px; height: 36px;
  padding: 0;
  background: #fff;
  border: 1px solid var(--border, #d8dce1);
  border-radius: var(--r-sm, 6px);
  color: var(--text-dim);
  display: inline-grid; place-items: center;
  cursor: pointer;
  transition: background var(--t-fast, 120ms) var(--ease, ease), color var(--t-fast, 120ms) var(--ease, ease), border-color var(--t-fast, 120ms) var(--ease, ease);
}
.plan-toolbar-icon-btn svg { width: 18px; height: 18px; }
.plan-toolbar-icon-btn:hover {
  background: color-mix(in srgb, var(--brand-primary, var(--red)) 10%, #fff);
  border-color: var(--brand-primary, var(--red));
  color: var(--brand-primary, var(--red));
}
.plan-toolbar-icon-btn:focus-visible {
  outline: 2px solid var(--brand-primary, var(--red));
  outline-offset: 2px;
}

/* Inline indicator that sits left of the Attach button when the plan is
   linked to an upcoming practice. Hidden via [hidden] when unused. */
.plan-attachment-indicator {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 5px 12px 5px 10px;
  font-size: 12px;
  font-weight: 600;
  letter-spacing: 0.2px;
  color: var(--brand-primary, var(--red));
  background: color-mix(in srgb, var(--brand-primary, var(--red)) 10%, #fff);
  border: 1px solid color-mix(in srgb, var(--brand-primary, var(--red)) 30%, transparent);
  border-radius: var(--r-pill, 999px);
  margin-right: 4px;
  cursor: default;
}
.plan-attachment-indicator::before {
  content: "";
  display: inline-block;
  width: 6px; height: 6px;
  border-radius: 50%;
  background: var(--brand-primary, var(--red));
}
/* `display: inline-flex` on the class beats UA `[hidden] { display: none }` at
   equal specificity, so re-assert the hide. Same pattern as .icon-grid[hidden]
   and .plans-edit-shell[hidden] elsewhere. */
.plan-attachment-indicator[hidden] { display: none; }
/* The history block has display:block by default, but it also gets toggled via
   the hidden attribute — be explicit for consistency. */
.plan-attachment-history[hidden] { display: none; }

/* History block under the Delete button — every practice (past + upcoming)
   this plan has been linked to. */
.plan-attachment-history {
  margin-top: 18px;
  padding-top: 14px;
  border-top: 1px solid var(--border-soft, #e6e8eb);
}
.plan-attachment-history-head {
  margin: 0 0 8px;
  font-size: 12px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 1px;
  color: var(--text-dim);
}
.plan-attachment-history-list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 4px;
}
.plan-attachment-history-item {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 6px 10px;
  font-size: 12.5px;
  color: var(--text);
  background: var(--bg-soft, #f4f5f7);
  border-radius: var(--r-sm, 6px);
  border-left: 3px solid transparent;
}
.plan-attachment-history-item.is-upcoming {
  border-left-color: var(--brand-primary, var(--red));
  background: color-mix(in srgb, var(--brand-primary, var(--red)) 5%, #fff);
}
.plan-attachment-history-date {
  font-weight: 700;
  min-width: 100px;
}
.plan-attachment-history-title {
  font-weight: 500;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.plan-attachment-history-meta {
  font-size: 11.5px;
  color: var(--text-dim);
  margin-left: auto;
  white-space: nowrap;
}
.plan-attachment-history-badge {
  font-size: 10px;
  font-weight: 800;
  letter-spacing: 0.6px;
  text-transform: uppercase;
  padding: 2px 7px;
  border-radius: var(--r-pill, 999px);
  background: var(--brand-primary, var(--red));
  color: #fff;
}

/* The Run Practice primary action keeps its label + a play icon. */
.plan-toolbar-run-btn {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 8px 14px;
  font-weight: 600;
  background: var(--brand-primary, var(--red)) !important;
  border-color: var(--brand-primary, var(--red)) !important;
  color: #fff !important;
  border-radius: var(--r-sm, 6px);
}
.plan-toolbar-run-btn svg { width: 14px; height: 14px; }
.plan-toolbar-run-btn:hover { filter: brightness(0.94); }
.plan-editor-actions {
  display: flex;
  gap: 8px;
  align-items: center;
  padding-top: 16px;
  border-top: 1px solid var(--border-soft, #e6e8eb);
}
.plan-editor-actions .btn-primary {
  background: var(--brand-primary, var(--red));
  border-color: var(--brand-primary, var(--red));
  color: #fff !important;
}

@media (max-width: 640px) {
  .plan-editor-head { grid-template-columns: 1fr; }
  .plan-editor-date { text-align: left; }
  .plan-editor-book { text-align: left; }
  .ped-row { grid-template-columns: 28px 1fr auto; }
  .ped-thumb { display: none; }
}

/* Schedule row: chip showing a Practice's attached plan. */
.schedule-plan-chip {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  margin-top: 6px;
  max-width: 100%;
  padding: 3px 10px;
  font-size: 10.5px;
  font-weight: 800;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  line-height: 1.5;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  color: #fff;
  background: var(--panel-dark, #2c3036);
  border: none;
  border-radius: 999px;
  transition: filter .15s;
}
.schedule-plan-chip .icon-inline { width: 13px; height: 13px; vertical-align: -2px; }

/* Plan editor — visibility toggle (CSS-only switch). */
.plan-visibility-toggle {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  margin: 6px 0 18px;
  cursor: pointer;
  user-select: none;
  font-size: 13px;
  color: var(--text);
}
.plan-visibility-toggle input { position: absolute; opacity: 0; pointer-events: none; }
.plan-visibility-track {
  width: 36px; height: 20px;
  background: var(--border, #d8dce1);
  border-radius: var(--r-pill, 999px);
  position: relative;
  transition: background var(--t-fast, 120ms) var(--ease, ease);
  flex: 0 0 auto;
}
.plan-visibility-thumb {
  position: absolute;
  top: 2px; left: 2px;
  width: 16px; height: 16px;
  background: #fff;
  border-radius: 50%;
  box-shadow: 0 1px 3px rgba(0,0,0,.25);
  transition: transform var(--t-fast, 120ms) var(--ease, ease);
}
.plan-visibility-toggle input:checked + .plan-visibility-track { background: var(--green, #1f9e5a); }
.plan-visibility-toggle input:checked + .plan-visibility-track .plan-visibility-thumb { transform: translateX(16px); }
.plan-visibility-toggle input:focus-visible + .plan-visibility-track { box-shadow: var(--ring); }
.plan-visibility-text { font-weight: 600; }

/* Clipboard badge — small pill at the bottom of the head block. */
.plan-visible-badge {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  margin-top: 6px;
  padding: 3px 9px;
  background: color-mix(in srgb, var(--green, #1f9e5a) 14%, #fff);
  color: var(--green, #1f9e5a);
  border-radius: var(--r-pill, 999px);
  font-size: 10.5px;
  font-weight: 700;
  letter-spacing: 0.4px;
  text-transform: uppercase;
}
.plan-visible-badge .icon-inline { width: 13px; height: 13px; }

/* Side-by-side share + visibility toggles inside the plan editor. */
.plan-visibility-row {
  display: flex;
  flex-wrap: wrap;
  gap: 24px;
  margin: 6px 0 18px;
}
.plan-visibility-row .plan-visibility-toggle { margin: 0; }

/* Clipboard chip: "📅 Oct 12 · Skating & Edges" — shown on a plan card when
   the plan is attached to an upcoming practice on the schedule. */
.plan-upcoming-chip {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  margin-top: 6px;
  padding: 3px 9px;
  background: color-mix(in srgb, var(--brand-primary, var(--red)) 12%, #fff);
  color: var(--brand-primary, var(--red));
  border: 1px solid color-mix(in srgb, var(--brand-primary, var(--red)) 28%, transparent);
  border-radius: var(--r-pill, 999px);
  font-size: 10.5px;
  font-weight: 700;
  letter-spacing: 0.3px;
  text-transform: uppercase;
}
.plan-upcoming-chip .icon-inline { width: 13px; height: 13px; }
/* Subtle highlight on the whole card when a plan has a scheduled practice. */
.plan-card.has-upcoming {
  box-shadow: 0 0 0 1px color-mix(in srgb, var(--brand-primary, var(--red)) 24%, transparent),
              0 6px 16px -8px rgba(0,0,0,.18),
              0 2px 4px -2px rgba(0,0,0,.08);
}

/* Sidebar version — same visual treatment as the date `.badge` in the meta
   row so plan attachments don't shout. Neutral grey background, dim text. */
.plan-side-upcoming {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  margin-top: 4px;
  padding: 1px 6px;
  background: var(--bg-soft);
  color: var(--text-dim);
  border-radius: 3px;
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0;
  max-width: 100%;
  overflow: hidden;
}
.plan-side-upcoming svg { width: 11px; height: 11px; flex-shrink: 0; opacity: 0.8; }
.plan-side-upcoming span {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* Clipboard badge for plans the current coach hasn't shared with their staff. */
.plan-private-badge {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  margin-top: 6px;
  margin-right: 4px;
  padding: 3px 9px;
  background: color-mix(in srgb, var(--text-dim) 14%, #fff);
  color: var(--text-dim);
  border-radius: var(--r-pill, 999px);
  font-size: 10.5px;
  font-weight: 700;
  letter-spacing: 0.4px;
  text-transform: uppercase;
}
.plan-private-badge .icon-inline { width: 13px; height: 13px; }

/* Clickable thumbnail in plan-editor rows — wraps the existing .ped-thumb img
   and overlays a magnifier on hover so the expand affordance is discoverable. */
.ped-thumb-btn {
  position: relative;
  display: block;
  width: 250px; height: 150px;
  padding: 0; margin: 0;
  border: 0;
  background: transparent;
  cursor: pointer;
  border-radius: var(--r-sm, 4px);
  overflow: hidden;
}
.ped-thumb-btn .ped-thumb {
  display: block;
  width: 100%; height: 100%;
  /* keep contain inside the button wrapper so the whole rink stays visible */
  object-fit: contain;
}
/* Hover zoom + magnifier overlay removed (Ian 2026-08-26) — the row image
   stays still; a plain click opens the drill preview. */
.ped-thumb-zoom { display: none; }
.ped-thumb-btn:focus-visible { outline: 2px solid var(--brand-primary, var(--red)); outline-offset: 2px; }

/* Drill preview modal — large image + description, opened from a row's
   magnifier button. */
.drill-preview-modal { padding: 22px 24px; }
.drill-preview-head {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 12px;
  margin-bottom: 16px;
  padding-bottom: 12px;
  border-bottom: 1px solid var(--border-soft, #e6e8eb);
}
.drill-preview-head .sub {
  font-size: 12px;
  color: var(--text-dim);
}
.drill-preview-body {
  display: grid;
  grid-template-columns: minmax(0, 1.4fr) minmax(0, 1fr);
  gap: 20px;
  align-items: start;
}
.drill-preview-image-wrap {
  background: var(--bg-soft, #f4f5f7);
  border: 1px solid var(--border-soft, #e6e8eb);
  border-radius: var(--r-md, 8px);
  padding: 8px;
  display: grid; place-items: center;
  min-height: 240px;
}
.drill-preview-image-wrap img {
  display: block;
  width: 100%;
  height: auto;
  max-height: 70vh;
  object-fit: contain;
  border-radius: var(--r-sm, 4px);
}
.drill-preview-description {
  font-size: 14px;
  line-height: 1.55;
  color: var(--text);
}
.drill-preview-description p { margin: 0 0 10px; }
.drill-preview-description ul,
.drill-preview-description ol { padding-left: 22px; margin: 0 0 10px; }
.drill-preview-description li { margin: 2px 0; }
.drill-preview-description h1,
.drill-preview-description h2,
.drill-preview-description h3,
.drill-preview-description h4 { margin: 10px 0 6px; font-size: 14px; font-weight: 700; }

@media (max-width: 720px) {
  .drill-preview-body { grid-template-columns: 1fr; }
  .drill-preview-image-wrap { min-height: 0; }
}

/* ============================================================
   Plans page — split layout
   Mirrors the rinkboard shell: editor takes the main area on the
   left, a compact plan list lives in a right-side sidebar.
   ============================================================ */
.page-plans-split { display: flex; flex-direction: column; min-height: 0; }
.plans-split {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 340px;
  gap: 20px;
  align-items: start;
  margin-top: 12px;
}
.plans-main { min-width: 0; }
.plans-sidebar {
  position: sticky;
  top: 12px;
  background: var(--panel, #fff);
  border: 1px solid var(--border-soft, #e6e8eb);
  border-radius: var(--r-md, 8px);
  overflow: hidden;
  max-height: calc(100vh - 140px);
  display: flex;
  flex-direction: column;
}
.plans-sidebar-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 12px 14px;
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 1px;
  text-transform: uppercase;
  color: var(--text-dim);
  border-bottom: 1px solid var(--border-soft, #e6e8eb);
  background: var(--bg-soft, #f4f5f7);
}
.plans-sidebar-count {
  font-size: 11px;
  font-weight: 700;
  padding: 2px 8px;
  border-radius: var(--r-pill, 999px);
  background: var(--brand-primary, var(--red));
  color: #fff;
  min-width: 22px;
  text-align: center;
  letter-spacing: 0;
}
.plans-sidebar #plan-list {
  overflow-y: auto;
  flex: 1;
  padding: 6px;
}
.plans-sidebar-empty {
  padding: 24px 16px;
  text-align: center;
  font-size: 13px;
  color: var(--text-dim);
  line-height: 1.5;
}

/* Compact plan row in the sidebar (mirrors the drill-list pattern). */
.plan-item {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  gap: 8px;
  align-items: center;
  padding: 10px 12px;
  border-radius: var(--r-sm, 6px);
  cursor: pointer;
  border: 1px solid transparent;
  transition: background var(--t-fast, 120ms) var(--ease, ease), border-color var(--t-fast, 120ms) var(--ease, ease);
}
.plan-item + .plan-item { margin-top: 2px; }
.plan-item:hover {
  background: color-mix(in srgb, var(--brand-primary, var(--red)) 6%, transparent);
  border-color: color-mix(in srgb, var(--brand-primary, var(--red)) 20%, transparent);
}
.plan-item.active {
  background: color-mix(in srgb, var(--brand-primary, var(--red)) 12%, transparent);
  border-color: var(--brand-primary, var(--red));
}
.plan-item-main { min-width: 0; }
.plan-item-title {
  font-weight: 700;
  font-size: 13px;
  color: var(--text);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.plan-item-meta {
  font-size: 11px;
  color: var(--text-dim);
  margin-top: 2px;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.plan-item-flags {
  display: inline-flex;
  gap: 4px;
  margin-top: 4px;
}
.plan-item-flag {
  display: inline-grid; place-items: center;
  width: 18px; height: 18px;
  border-radius: var(--r-sm, 4px);
  background: var(--bg-soft, #f4f5f7);
  color: var(--text-dim);
}
.plan-item-flag.visible { background: color-mix(in srgb, var(--green, #1f9e5a) 14%, #fff); color: var(--green, #1f9e5a); }
.plan-item-flag.private { background: color-mix(in srgb, var(--text-dim) 14%, #fff); color: var(--text-dim); }
.plan-item-flag .icon-inline { width: 12px; height: 12px; }
.plan-item-del {
  background: transparent;
  border: 0;
  width: 28px; height: 28px;
  border-radius: var(--r-sm, 6px);
  color: var(--text-dim);
  display: inline-grid; place-items: center;
  cursor: pointer;
  opacity: 0;
  transition: opacity var(--t-fast, 120ms) var(--ease, ease), background var(--t-fast, 120ms) var(--ease, ease), color var(--t-fast, 120ms) var(--ease, ease);
}
.plan-item:hover .plan-item-del,
.plan-item:focus-within .plan-item-del,
.plan-item.active .plan-item-del { opacity: 1; }
.plan-item-del:hover { background: color-mix(in srgb, var(--red) 12%, transparent); color: var(--red); }
.plan-item-del .icon-inline { width: 14px; height: 14px; }

/* Empty-state shown in the main area when no plan is open. */
.plans-empty {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  text-align: center;
  padding: 60px 24px;
  min-height: 420px;
  border: 2px dashed var(--border-soft, #e6e8eb);
  border-radius: var(--r-md, 8px);
  color: var(--text-dim);
}
.plans-empty-icon svg { width: 56px; height: 56px; color: var(--text-dim); opacity: 0.7; }
.plans-empty h2 {
  margin: 14px 0 6px;
  font-size: 18px;
  font-weight: 700;
  color: var(--text);
}
.plans-empty p { margin: 0; font-size: 14px; max-width: 360px; line-height: 1.55; }
.plans-empty b { color: var(--brand-primary, var(--red)); }

/* Editor sits in the main area now — give it a panel surround so it visually
   reads as a "view" rather than free-floating content. */
.page-plans-split .plan-editor {
  background: var(--panel, #fff);
  border: 1px solid var(--border-soft, #e6e8eb);
  border-radius: var(--r-md, 8px);
  padding: 20px;
}

/* Sidebar collapses below the editor on narrower viewports. */
@media (max-width: 980px) {
  .plans-split { grid-template-columns: 1fr; }
  .plans-sidebar { position: static; max-height: 360px; }
}

/* ============================================================
   Plans EDIT shell — full-bleed view mirroring the rinkboard
   layout (drill page). Activated when at least one plan is open
   in a tab; the clipboard grid view is hidden during this state.
   ============================================================ */
.plans-edit-shell {
  display: flex;
  flex-direction: column;
  height: calc(100vh - 52px);
  background: var(--bg, #fff);
  color: var(--text);
}
/* `.plans-edit-shell { display: flex }` ties with the UA `[hidden] { display:none }`
   at the same specificity (1 class vs 1 attr), so the later page-CSS wins and the
   element would render even with `hidden`. Force the hide here. Same pattern for
   the grid view since it gets toggled too. */
.plans-edit-shell[hidden],
#plans-grid-view[hidden] { display: none; }
body.plans-edit-mode .page-main { height: calc(100vh - 52px); overflow: hidden; }

.plans-edit-bar {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 10px 16px;
  /* Light background so it visually separates from the dark .topnav above it
     (mirrors the drill-page .topbar pattern). */
  background: var(--bg, #fff);
  border-bottom: 1px solid var(--border-soft, #e6e8eb);
  flex: 0 0 auto;
  min-height: 52px;
}
.plans-edit-bar-spacer { flex: 1; }
.plans-back-btn {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  background: transparent;
  border: 1px solid var(--border, #d8dce1);
  color: var(--text);
  padding: 6px 12px 6px 8px;
  border-radius: var(--r-sm, 6px);
  cursor: pointer;
  font-size: 13px;
  font-weight: 600;
  transition: background var(--t-fast, 120ms) var(--ease, ease), border-color var(--t-fast, 120ms) var(--ease, ease);
}
.plans-back-btn:hover {
  background: color-mix(in srgb, var(--brand-primary, var(--red)) 8%, transparent);
  border-color: var(--brand-primary, var(--red));
  color: var(--brand-primary, var(--red));
}
.plans-back-btn svg { width: 16px; height: 16px; }
.plans-edit-bar .plan-tab-strip {
  flex: 0 1 auto;
  margin: 0;
  background: transparent;
  border: 0;
  padding: 0;
}

.plans-edit-main {
  flex: 1;
  display: grid;
  grid-template-columns: minmax(0, 1fr) 320px;
  grid-template-rows: 1fr;   /* row fills the flex height — without this the
                                row is auto-sized to content (~56px) and the
                                editor only shows a sliver */
  min-height: 0;
  background: var(--bg-soft, #f4f5f7);
  position: relative;
}
/* Collapse strip — sits flush against the right edge of the main area when
   the plans sidebar is hidden. Click it to expand the sidebar back in. */
.plans-collapse-strip {
  position: absolute;
  top: 0;
  right: 0;
  width: 18px;
  height: 100%;
  display: none;
  align-items: center;
  justify-content: center;
  background: var(--panel-dark, #2c3036);
  color: rgba(255, 255, 255, 0.75);
  border: 0;
  cursor: pointer;
  z-index: 4;
  transition: background var(--t-fast, 120ms) var(--ease, ease), color var(--t-fast, 120ms) var(--ease, ease);
}
.plans-collapse-strip:hover {
  background: var(--brand-primary, var(--red));
  color: #fff;
}
.plans-collapse-strip svg { width: 14px; height: 14px; }

/* Collapsed state */
body.plans-sidebar-collapsed .plans-edit-main { grid-template-columns: 1fr; }
body.plans-sidebar-collapsed .plans-edit-sidebar { display: none; }
body.plans-sidebar-collapsed .plans-collapse-strip { display: flex; }
body.plans-sidebar-collapsed .plans-edit-canvas { padding-right: 18px; } /* leave room for the strip */
.plans-edit-canvas {
  overflow-y: auto;
  min-width: 0;
  min-height: 0;             /* lets the auto-scrolling work inside the grid */
  background: var(--panel, #fff);
  /* Stack the editor and the sticky add-bar vertically so we can pin the bar
     to the bottom regardless of editor height. */
  display: flex;
  flex-direction: column;
}
.plans-edit-canvas > .plan-editor { flex: 1 0 auto; }
/* Sticky bottom bar inside the scrolling canvas — always visible without
   scrolling, even on plans with many drills. */
.plan-editor-add-bar {
  position: sticky;
  bottom: 0;
  z-index: 5;
  background: #fff;
  border-top: 1px solid var(--border-soft, #e6e8eb);
  box-shadow: 0 -6px 14px -10px rgba(0,0,0,0.18);
  padding: 12px 24px;
  margin-top: auto; /* push to the bottom when the editor is short */
}
.plan-editor-add-bar .plan-editor-add-row { margin: 0; }
/* Editor stretches edge-to-edge across the canvas column (viewport width minus
   the 320px Plans sidebar). Drops all the card chrome since the canvas itself
   is the surface now — no border, no rounded corners, no horizontal padding so
   inputs and drill rows touch the sidebar edge. Vertical padding only. */
.plans-edit-canvas .plan-editor {
  width: 100%;
  max-width: none;
  margin: 0;
  background: transparent;
  border: 0 !important;
  border-radius: 0;
  padding: 20px 0;
  box-shadow: none;
}
/* Inside the canvas, push each editor row to the canvas edges with a thin
   inset so text doesn't crash into the sidebar border. */
.plans-edit-canvas .plan-editor > * {
  padding-left: 24px;
  padding-right: 24px;
}
.plans-edit-canvas .plan-editor-drill-list { padding-left: 24px; padding-right: 24px; }

/* Right sidebar — reuses .sidebar / .sidebar-tabs / .drill-list scaffolding so
   it matches the rinkboard look exactly. */
.plans-edit-sidebar {
  background: var(--bg);
  border-left: 1px solid var(--border-soft);
  display: flex;
  flex-direction: column;
  overflow: hidden;
  min-width: 0;
}
.plans-edit-sidebar .sidebar-tabs {
  display: flex;
  background: var(--panel-dark);
  border-bottom: 1px solid #1a1d22;
}
.plans-edit-sidebar .sidebar-tab {
  flex: 1;
  text-align: center;
  padding: 12px 8px;
  cursor: default;
  font-weight: 700;
  font-size: 12px;
  letter-spacing: 1px;
  color: rgba(255,255,255,.65);
  border-bottom: 3px solid transparent;
}
.plans-edit-sidebar .sidebar-tab.active {
  color: #fff;
  border-bottom-color: var(--brand-primary, var(--red));
}
.plans-edit-sidebar .sidebar-panel { display: flex; flex: 1; flex-direction: column; overflow: hidden; }
.plans-edit-sidebar .search-row { padding: 8px 12px; border-bottom: 1px solid var(--border-soft); }
.plans-edit-sidebar .search-row input {
  width: 100%;
  border: 1px solid var(--border, #d8dce1);
  padding: 7px 12px;
  border-radius: 3px;
  font-family: inherit;
  font-size: 13px;
  text-transform: uppercase;
  letter-spacing: 0.5px;
  color: var(--text);
  background: #fff;
  outline: none;
}
.plans-edit-sidebar .drill-list {
  flex: 1;
  overflow-y: auto;
  padding: 6px;
}
/* Sidebar plan cards stay neutral grey/light-grey — no brand color tint on
   hover or when active. The chip(s) inside (upcoming-practice etc.) still
   carry color for status, but the card itself blends with the panel. */
.plan-side-card {
  border-color: var(--border-soft, #e6e8eb) !important;
  background: #fff !important;
}
.plan-side-card:hover {
  background: var(--bg-soft, #f4f5f7) !important;
  border-color: var(--border, #d8dce1) !important;
}
/* Active plan = solid red card with white text. Inverts the chip and badge
   colors so they stay legible against the red surface. */
.plan-side-card.active {
  background: var(--red) !important;
  border-color: var(--red) !important;
  color: #fff !important;
}
.plan-side-card.active .nm,
.plan-side-card.active .info { color: #fff !important; }
.plan-side-card.active .meta { color: rgba(255, 255, 255, 0.88) !important; }
.plan-side-card.active .meta .badge {
  background: rgba(255, 255, 255, 0.20) !important;
  color: #fff !important;
}
.plan-side-card.active .acts button {
  color: rgba(255, 255, 255, 0.85) !important;
}
.plan-side-card.active .acts button:hover {
  background: rgba(255, 255, 255, 0.15) !important;
  color: #fff !important;
}
/* The "Added to practice…" chip matches the date `.badge` override on an
   active card — translucent white on the red background, white text. */
.plan-side-card.active .plan-side-upcoming {
  background: rgba(255, 255, 255, 0.20) !important;
  color: #fff !important;
}
.plan-side-card.active .plan-side-upcoming svg { opacity: 1; }
.plan-side-card .meta { flex-wrap: wrap; }
.plan-side-card .meta .badge { font-weight: 600; }

/* Books — collapsible groups of plans in the sidebar. Mirrors the
   .drill-folder-group pattern from the rinkboard's drill list. */
.plan-book-group { margin-bottom: 6px; }
.plan-book-head {
  display: flex;
  align-items: center;
  gap: 6px;
  padding: 8px 8px 6px;
  cursor: pointer;
  color: var(--text-dim);
  font-size: 11px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.7px;
  user-select: none;
  border-radius: var(--r-sm, 4px);
}
.plan-book-head:hover { background: var(--bg-soft, #f4f5f7); color: var(--text); }
.plan-book-head .chev {
  transition: transform var(--t-fast, 120ms) var(--ease, ease);
  flex-shrink: 0;
}
.plan-book-group.collapsed .plan-book-head .chev { transform: rotate(-90deg); }
/* "Current" book = the one containing the active plan. Uses the topnav's
   panel-dark color so the book the user is working inside is visually
   anchored to the page chrome. Also bumped a notch larger than the normal
   book heading. */
.plan-book-group.is-current .plan-book-head {
  background: var(--panel-dark, #2c3036);
  color: #fff;
  font-size: 13px;
  letter-spacing: 0.5px;
  padding: 11px 12px 10px;
}
.plan-book-group.is-current .plan-book-head:hover {
  background: var(--panel-dark, #2c3036);
  color: #fff;
}
.plan-book-group.is-current .plan-book-head .chev { width: 12px; height: 12px; }
.plan-book-group.is-current .plan-book-count {
  background: rgba(255, 255, 255, 0.22);
  color: #fff;
  font-size: 11.5px;
  padding: 2px 9px;
}
.plan-book-label {
  flex: 1;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.plan-book-count {
  background: var(--bg-soft, #f4f5f7);
  color: var(--text-dim);
  padding: 1px 7px;
  border-radius: var(--r-pill, 999px);
  font-size: 10.5px;
  font-weight: 700;
  letter-spacing: 0;
}
.plan-book-group.collapsed .plan-book-body { display: none; }

/* Overflow indicator for the clipboard grid when a plan has > 8 drills. */
.plan-drill-overflow {
  font-size: 11px;
  font-weight: 600;
  color: var(--text-dim);
  padding: 6px 4px 2px;
  text-align: right;
  font-style: italic;
}

@media (max-width: 860px) {
  .plans-edit-main { grid-template-columns: 1fr; }
  .plans-edit-sidebar { display: none; }
  .plans-edit-bar { flex-wrap: wrap; }
  /* Stack the name / books / date fields — three columns can't fit. */
  .plan-editor-head { grid-template-columns: 1fr; gap: 8px; }
  .plans-edit-canvas .plan-editor > *,
  .plans-edit-canvas .plan-editor-drill-list { padding-left: 14px; padding-right: 14px; }
  .plan-editor-add-bar { padding: 10px 14px; }
}

/* "Add personal drill to my teams" picker — list of checkboxes inside the
   push-to-teams modal. */
.push-to-teams-list {
  display: flex;
  flex-direction: column;
  gap: 4px;
  max-height: 320px;
  overflow-y: auto;
  margin-bottom: 12px;
}
.push-team-row {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 8px 10px;
  border: 1px solid var(--border-soft, #e6e8eb);
  border-radius: var(--r-sm, 6px);
  cursor: pointer;
  font-size: 13px;
  transition: border-color var(--t-fast, 120ms) var(--ease, ease), background var(--t-fast, 120ms) var(--ease, ease);
}
.push-team-row:hover {
  background: color-mix(in srgb, var(--brand-primary, var(--red)) 6%, #fff);
  border-color: var(--brand-primary, var(--red));
}
.push-team-row input[type="checkbox"] { width: 16px; height: 16px; flex-shrink: 0; }
.push-team-name { flex: 1; font-weight: 600; }
.push-team-row .badge {
  background: var(--bg-soft, #f4f5f7);
  color: var(--text-dim);
  padding: 1px 6px;
  border-radius: 3px;
  font-size: 11px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.4px;
}

/* ============================================================
   Add Drill to Plan — redesigned picker modal
   Wider modal, card grid with bigger thumbs, scope tabs, search,
   popularity badge, "in plan" pill, per-card mins override.
   ============================================================ */
.modal.add-drill-modal {
  width: 1200px;
  max-width: 96vw;
  /* Definite height (not just max-height) — flex children inside need a
     concrete parent height to allocate space correctly. Without this the
     picker's flex: 1 falls back to content size and the grid rows squish. */
  height: 88vh;
  max-height: 88vh;
  padding: 0;
  display: flex;
  flex-direction: column;
  overflow: hidden;
}
.add-drill-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 16px 20px;
  border-bottom: 1px solid var(--border-soft, #e6e8eb);
}
.add-drill-head h3 { margin: 0; font-size: 18px; }
.add-drill-toolbar {
  display: flex;
  gap: 12px;
  align-items: center;
  padding: 12px 20px;
  border-bottom: 1px solid var(--border-soft, #e6e8eb);
  background: var(--bg-soft, #f4f5f7);
}
.add-drill-toolbar input[type="text"] {
  flex: 1;
  padding: 8px 12px;
  border: 1px solid var(--border, #d8dce1);
  border-radius: var(--r-sm, 6px);
  font-size: 13px;
  background: #fff;
  outline: none;
}
.add-drill-toolbar input[type="text"]:focus {
  border-color: var(--brand-primary, var(--red));
}
.add-drill-scope {
  display: inline-flex;
  background: #fff;
  border: 1px solid var(--border-soft, #e6e8eb);
  border-radius: var(--r-pill, 999px);
  padding: 2px;
  gap: 2px;
  flex-shrink: 0;
}
.add-drill-scope button {
  padding: 5px 14px;
  font-size: 12px;
  font-weight: 600;
  background: transparent;
  border: 0;
  border-radius: var(--r-pill, 999px);
  cursor: pointer;
  color: var(--text-dim);
  letter-spacing: 0.2px;
}
.add-drill-scope button.active {
  background: var(--brand-primary, var(--red));
  color: #fff;
}
.add-drill-scope button:hover:not(.active) { color: var(--text); }

/* View toggle (Grid / Compact / Detail) — icon-only pill group. */
.add-drill-view {
  display: inline-flex;
  background: #fff;
  border: 1px solid var(--border-soft, #e6e8eb);
  border-radius: var(--r-sm, 6px);
  overflow: hidden;
  flex-shrink: 0;
}
.add-drill-view button {
  width: 32px; height: 30px;
  display: inline-grid; place-items: center;
  background: transparent;
  border: 0;
  cursor: pointer;
  color: var(--text-dim);
  padding: 0;
}
.add-drill-view button svg { width: 16px; height: 16px; }
.add-drill-view button:hover { color: var(--text); background: var(--bg-soft, #f4f5f7); }
.add-drill-view button.active {
  background: var(--text);
  color: #fff;
}
.add-drill-view button + button { border-left: 1px solid var(--border-soft, #e6e8eb); }

/* Flex-wrap layout (NOT CSS Grid). CSS Grid was distributing the picker's
   vertical space across rows once the modal hit its max-height — every card
   got 1/N of available height instead of holding its 290px content height.
   Flex-wrap rows are content-sized: each row is exactly as tall as the
   tallest card in it, and the picker scrolls when total height exceeds it. */
#drill-picker {
  display: flex;
  flex-wrap: wrap;
  align-content: flex-start;
  align-items: flex-start;
  gap: 14px;
  overflow-y: auto;
  flex: 1 1 auto;
  min-height: 0;
  padding: 16px 20px;
  margin: 0;
  border: 0;
  max-height: none;
  background: var(--panel, #fff);
}
/* Grid view — three cards per row (responsive: 2 on narrow, 1 on tiny). */
#drill-picker .pick-card { flex: 0 0 calc((100% - 28px) / 3); }
@media (max-width: 900px) { #drill-picker .pick-card { flex-basis: calc((100% - 14px) / 2); } }
@media (max-width: 640px) { #drill-picker .pick-card { flex-basis: 100%; } }

/* Compact list view — small thumb on the left, name + meta + actions on a
   single line. One drill per row. */
#drill-picker.pick-view-compact {
  /* Keep flex-direction: row + flex-wrap: wrap from the base rule. With each
     card at flex: 0 0 100% (below), wrapping happens vertically — top-to-
     bottom rows. Setting flex-direction: column here would combine with the
     inherited flex-wrap: wrap to create LEFT-TO-RIGHT column flow (cards
     stack down, then wrap rightward) which causes horizontal scroll. */
  gap: 4px;
}
#drill-picker.pick-view-compact .pick-card {
  flex: 0 0 100%;     /* one drill per row in compact view */
  flex-direction: row;
  align-items: center;
  min-height: 58px;   /* matches the fixed-width thumb height */
}
#drill-picker.pick-view-compact .pick-card-thumb {
  width: 96px;
  height: 58px;        /* 96 × 3/5, fixed (padding-bottom % is relative to
                          parent width, so use explicit height instead). */
  padding-bottom: 0;
  flex-shrink: 0;
}
#drill-picker.pick-view-compact .pick-card-thumb-empty { font-size: 10px; }
#drill-picker.pick-view-compact .pick-card-added-pill,
#drill-picker.pick-view-compact .pick-card-pop {
  font-size: 10px;
  padding: 2px 6px;
}
#drill-picker.pick-view-compact .pick-card-added-pill svg,
#drill-picker.pick-view-compact .pick-card-pop svg { width: 10px; height: 10px; }
#drill-picker.pick-view-compact .pick-card-body {
  flex: 1;
  flex-direction: row;
  align-items: center;
  gap: 14px;
  padding: 10px 14px;
  min-width: 0;
}
#drill-picker.pick-view-compact .pick-card-name { flex: 0 1 auto; font-size: 13.5px; }
#drill-picker.pick-view-compact .pick-card-meta { flex: 1; font-size: 12px; }
#drill-picker.pick-view-compact .pick-card-actions { margin-top: 0; }

/* Detail row view — bigger thumb + meta + description preview, one per row. */
#drill-picker.pick-view-detail {
  /* Same fix as compact view — keep flex-direction: row from the base rule
     so flex-wrap: wrap creates vertical rows of full-width cards. */
  gap: 10px;
}
#drill-picker.pick-view-detail .pick-card {
  flex: 0 0 100%;     /* one drill per row in detail view */
  flex-direction: row;
  align-items: stretch;
  min-height: 192px;   /* matches the fixed-width thumb height */
}
#drill-picker.pick-view-detail .pick-card-thumb {
  width: 320px;
  height: 192px;       /* 320 × 3/5, fixed for the same reason as compact. */
  padding-bottom: 0;
  flex-shrink: 0;
}
#drill-picker.pick-view-detail .pick-card-body {
  flex: 1;
  padding: 14px 18px;
  gap: 6px;
  min-width: 0;
}
#drill-picker.pick-view-detail .pick-card-name { font-size: 16px; }
#drill-picker.pick-view-detail .pick-card-meta { font-size: 13px; }
.pick-card-desc {
  font-size: 12.5px;
  line-height: 1.45;
  color: var(--text-dim);
  display: -webkit-box;
  -webkit-line-clamp: 3;
  -webkit-box-orient: vertical;
  overflow: hidden;
  margin: 4px 0;
}
#drill-picker.pick-view-detail .pick-card-actions { margin-top: auto; }
.pick-empty {
  grid-column: 1 / -1;
  text-align: center;
  padding: 32px 16px;
  color: var(--text-dim);
  font-size: 13px;
}
/* Load-more footer — spans the full grid row / flex column, gives count
   feedback and a click target if scroll-detection misfires. */
.pick-more {
  grid-column: 1 / -1;
  text-align: center;
  padding: 18px 12px;
  color: var(--text-dim);
  font-size: 12px;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 12px;
}
.pick-more-btn {
  background: var(--brand-primary, var(--red));
  border: 0;
  border-radius: var(--r-sm, 6px);
  color: #fff;
  padding: 6px 14px;
  font-size: 12px;
  font-weight: 700;
  cursor: pointer;
}
.pick-more-btn:hover { filter: brightness(0.94); }

/* Drill card — bigger thumb, name + meta, popularity badge, mins override.
   `align-self: start` keeps each card hugging its content height instead of
   stretching to whatever's tallest in the grid row — grid items default to
   stretch which was forcing every card to a single 60-ish-px row. */
.pick-card {
  display: flex;
  flex-direction: column;
  border: 1px solid var(--border-soft, #e6e8eb);
  border-radius: var(--r-md, 8px);
  background: #fff;
  overflow: hidden;
  align-self: start;
  min-height: 290px;
  transition: border-color var(--t-fast, 120ms) var(--ease, ease), box-shadow var(--t-fast, 120ms) var(--ease, ease), transform var(--t-fast, 120ms) var(--ease, ease);
}
/* Compact + detail views need their own height behavior (one-row layout). */
#drill-picker.pick-view-compact .pick-card,
#drill-picker.pick-view-detail  .pick-card { min-height: 0; align-self: stretch; }
.pick-card:hover {
  border-color: var(--brand-primary, var(--red));
  box-shadow: 0 6px 16px -8px rgba(0,0,0,0.12);
  transform: translateY(-1px);
}
.pick-card.is-added {
  border-color: color-mix(in srgb, var(--green, #1f9e5a) 50%, transparent);
  background: color-mix(in srgb, var(--green, #1f9e5a) 5%, #fff);
}
/* Thumb sizing uses an explicit pixel height to avoid aspect-ratio /
   padding-bottom edge cases inside flex+grid parents that have been
   silently collapsing the box. Image inside letterboxes via object-fit. */
.pick-card-thumb {
  position: relative;
  width: 100%;
  height: 180px;
  background: var(--bg-soft, #f4f5f7);
  overflow: hidden;
  flex-shrink: 0;
}
.pick-card-thumb > img {
  display: block;
  width: 100%; height: 100%;
  object-fit: contain;
}
.pick-card-thumb-empty {
  position: absolute;
  inset: 0;
  display: grid; place-items: center;
  font-size: 11px;
  color: var(--text-dim);
  font-style: italic;
}
.pick-card-pop {
  position: absolute;
  top: 8px; right: 8px;
  display: inline-flex;
  align-items: center;
  gap: 3px;
  padding: 3px 8px;
  background: color-mix(in srgb, var(--brand-secondary, #2864c8) 14%, #fff);
  color: var(--brand-secondary, #2864c8);
  border-radius: var(--r-pill, 999px);
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.2px;
  border: 1px solid color-mix(in srgb, var(--brand-secondary, #2864c8) 25%, transparent);
}
.pick-card-pop svg { width: 11px; height: 11px; }
.pick-card-added-pill {
  position: absolute;
  top: 8px; left: 8px;
  display: inline-flex;
  align-items: center;
  gap: 4px;
  padding: 3px 9px;
  background: var(--green, #1f9e5a);
  color: #fff;
  border-radius: var(--r-pill, 999px);
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.3px;
  text-transform: uppercase;
}
.pick-card-added-pill svg { width: 12px; height: 12px; }
.pick-card-body {
  padding: 10px 12px 12px;
  display: flex;
  flex-direction: column;
  gap: 4px;
  flex-shrink: 0;
}
.pick-card-name {
  font-weight: 700;
  font-size: 14px;
  color: var(--text);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.pick-card-meta {
  font-size: 12px;
  color: var(--text-dim);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.pick-card-actions {
  display: flex;
  gap: 8px;
  align-items: center;
  margin-top: 8px;
}
.pick-card-mins {
  position: relative;
  flex: 0 0 86px;
}
.pick-card-mins input {
  width: 100%;
  padding: 6px 28px 6px 10px;
  font-size: 12px;
  border: 1px solid var(--border, #d8dce1);
  border-radius: var(--r-sm, 6px);
  background: #fff;
  outline: none;
}
.pick-card-mins input:focus { border-color: var(--brand-primary, var(--red)); }
.pick-card-mins span {
  position: absolute;
  right: 10px; top: 50%;
  transform: translateY(-50%);
  font-size: 10.5px;
  color: var(--text-dim);
  pointer-events: none;
  font-weight: 600;
  letter-spacing: 0.3px;
  text-transform: uppercase;
}
.pick-card-actions .btn {
  flex: 1;
  padding: 7px 10px;
  font-size: 12.5px;
  font-weight: 700;
}

@media (max-width: 720px) {
  .modal.add-drill-modal { width: 100%; height: 100%; max-height: 100%; max-width: 100%; border-radius: 0; }
  .add-drill-toolbar { flex-wrap: wrap; }
  .add-drill-scope { width: 100%; justify-content: space-between; }
  #drill-picker { grid-template-columns: 1fr; }
}

/* ============================================================
   BILLING — trial banner + paywall modal
   ============================================================ */

/* Trial banner: thin strip below the topnav. Friendly tone for the
   countdown; switches to urgent red when the trial has expired. */
.billing-banner {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 12px;
  padding: 8px 16px;
  background: linear-gradient(180deg, #fff7e0 0%, #ffeaa6 100%);
  border-bottom: 1px solid #e6c860;
  color: #6a4a00;
  font-size: 13px;
  font-weight: 600;
  flex-wrap: wrap;
}
.billing-banner--expired {
  background: linear-gradient(180deg, #fff0f0 0%, #ffcccc 100%);
  border-bottom-color: #dc2626;
  color: #7a1612;
}
.billing-banner-text { line-height: 1.35; }

/* "READ ONLY" pill on the expired banner — visually distinct so the
   coach catches at a glance that the team is in read-only mode (not
   just "you have a banner"). Uppercase, brand red, monospace tracking. */
.billing-banner-pill {
  display: inline-flex;
  align-items: center;
  margin-right: 10px;
  padding: 3px 8px;
  font-size: 10.5px;
  font-weight: 800;
  letter-spacing: 1.2px;
  background: #dc2626;
  color: #fff;
  border-radius: 4px;
  text-transform: uppercase;
  white-space: nowrap;
  flex-shrink: 0;
}
.billing-banner-btn {
  background: var(--brand-primary, #7c5cff);
  color: #fff;
  border: 0;
  border-radius: 6px;
  padding: 6px 14px;
  font: inherit;
  font-weight: 700;
  cursor: pointer;
  transition: filter .12s ease;
}
.billing-banner-btn:hover { filter: brightness(1.08); }
.billing-banner-close {
  background: transparent;
  border: 0;
  color: inherit;
  opacity: 0.55;
  cursor: pointer;
  padding: 4px 6px;
  margin-left: 4px;
  display: inline-grid;
  place-items: center;
  border-radius: 4px;
  transition: opacity .12s ease, background .12s ease;
}
.billing-banner-close:hover { opacity: 1; background: rgba(0,0,0,0.06); }

/* Offline mode — pill in topnav appears only when body.is-offline is set
   (init.js toggles based on navigator.onLine + boot fallback). */
.offline-pill {
  display: none;
  align-items: center;
  gap: 6px;
  padding: 4px 10px;
  background: #fde2e2;
  color: #7a1612;
  border: 1px solid #f5b8b8;
  border-radius: 999px;
  font-size: 12px;
  font-weight: 700;
  letter-spacing: 0.3px;
  cursor: default;
  user-select: none;
}
.offline-pill svg { display: block; }
body.is-offline .offline-pill { display: inline-flex; }
/* Faint pulse on the page so the user feels they're in a different mode. */
body.is-offline .topnav { box-shadow: inset 0 -2px 0 0 #f5b8b8; }

/* When the banner is showing, the route-drill page-main height calc needs
   to reserve 36px for it. layout.php and body.route-drill .page-main use
   100vh - 52px; with the banner we subtract another 36px. */
body.route-drill:has(.billing-banner) .page-main { height: calc(100vh - 88px); }

/* Paywall modal — shown when a 402 comes back from the server. */
.paywall-modal-bg {
  display: none;
  position: fixed; inset: 0;
  background: rgba(20, 22, 26, 0.62);
  z-index: 10000;
  align-items: center;
  justify-content: center;
}
.paywall-modal-bg.show { display: flex; }
.paywall-modal {
  background: #fff;
  width: 100%;
  max-width: 460px;
  border-radius: 14px;
  padding: 28px 28px 22px;
  box-shadow: 0 16px 48px rgba(0,0,0,0.32);
}
.paywall-modal h2 {
  margin: 0 0 8px;
  font-size: 22px;
  font-weight: 800;
  color: var(--text);
}
.paywall-modal .sub {
  margin: 0 0 18px;
  color: var(--text-dim);
  font-size: 14px;
  line-height: 1.45;
}
.paywall-options {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 10px;
  margin-bottom: 12px;
}
.paywall-option {
  border: 2px solid var(--border);
  background: #fff;
  border-radius: 10px;
  padding: 14px 12px;
  cursor: pointer;
  text-align: center;
  transition: border-color .12s, transform .08s;
}
.paywall-option:hover { border-color: var(--brand-primary, #7c5cff); }
.paywall-option:active { transform: scale(0.985); }
.paywall-option-cadence { font-size: 11px; font-weight: 700; color: var(--text-dim); letter-spacing: 1.2px; text-transform: uppercase; }
.paywall-option-tag {
  display: inline-block;
  margin-left: 6px;
  padding: 2px 6px;
  font-size: 9.5px;
  font-weight: 800;
  letter-spacing: 0.8px;
  color: #0d6033;
  background: #d8f3df;
  border-radius: 4px;
  vertical-align: middle;
}
.paywall-option-price { font-size: 22px; font-weight: 800; color: var(--text); margin-top: 4px; }
.paywall-option-sub { font-size: 12px; color: var(--text-dim); margin-top: 4px; }
.paywall-option--annual { border-color: #1f9e5a; }
.paywall-option--annual::before {
  content: 'Best value';
  display: inline-block;
  background: #1f9e5a;
  color: #fff;
  font-size: 10px;
  font-weight: 800;
  letter-spacing: 0.5px;
  padding: 2px 6px;
  border-radius: 4px;
  margin-bottom: 4px;
}
.paywall-modal-foot {
  display: flex;
  justify-content: flex-end;
  margin-top: 10px;
}
.paywall-modal-close {
  background: transparent;
  border: 0;
  color: var(--text-dim);
  font: inherit;
  font-size: 13px;
  cursor: pointer;
  padding: 6px 10px;
}
.paywall-modal-close:hover { color: var(--text); }

/* Billing section on the Team settings page (M4). */
.billing-card {
  background: #fff;
  border: 1px solid var(--border-soft);
  border-radius: 10px;
  padding: 18px 20px;
  margin-top: 16px;
}
.billing-card h3 { margin: 0 0 6px; font-size: 16px; font-weight: 700; }
.billing-card .meta {
  font-size: 13px;
  color: var(--text-dim);
  margin-bottom: 14px;
  line-height: 1.5;
}
.billing-card .actions {
  display: flex;
  gap: 10px;
  flex-wrap: wrap;
}
.billing-card .pill {
  display: inline-block;
  padding: 2px 8px;
  border-radius: 999px;
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.4px;
  text-transform: uppercase;
  vertical-align: middle;
}
.billing-card .pill--trial    { background: #fff7e0; color: #6a4a00; }
.billing-card .pill--active   { background: #e7f8ee; color: #135f31; }
.billing-card .pill--expired,
.billing-card .pill--canceled,
.billing-card .pill--past_due { background: #fde2e2; color: #7a1612; }

/* Prominent billing facts (Plan / Next bill) — flat tiles, brand-accent date */
.billing-card .billing-facts { display: flex; flex-wrap: wrap; gap: 10px; margin-top: 4px; }
.billing-card .bf {
  display: flex; flex-direction: column; gap: 3px;
  padding: 10px 14px; min-width: 130px;
  border: 1px solid #e5e7eb; border-radius: 10px; background: #f8fafc;
}
.billing-card .bf-label {
  font-size: 11px; font-weight: 700; letter-spacing: .04em;
  text-transform: uppercase; color: #64748b;
}
.billing-card .bf-value { font-size: 17px; font-weight: 800; color: #0f172a; line-height: 1.1; }
.billing-card .bf-date { color: var(--brand-primary, #2563eb); }
.billing-card .billing-portal-hint { display: block; margin-top: 6px; font-size: 12px; color: #64748b; }

/* Billing history (in-app invoice list) */
.billing-history-card h3 { margin: 0 0 8px; font-size: 16px; font-weight: 700; }
.billing-invoices { display: flex; flex-direction: column; }
.billing-invoices .bi-loading,
.billing-invoices .bi-empty { font-size: 13px; color: #64748b; padding: 6px 0; }
.bi-row { display: flex; align-items: center; gap: 12px; padding: 10px 2px; border-bottom: 1px solid #eef2f7; }
.bi-row:last-child { border-bottom: 0; }
.bi-main { display: flex; flex-direction: column; gap: 1px; min-width: 0; flex: 1; }
.bi-date { font-weight: 700; color: #0f172a; font-size: 14px; }
.bi-num { font-size: 11px; color: #94a3b8; }
.bi-amt { font-weight: 700; color: #0f172a; font-size: 14px; white-space: nowrap; }
.bi-status { font-size: 11px; font-weight: 700; text-transform: capitalize; padding: 2px 9px; border-radius: 999px; background: #f1f5f9; color: #475569; }
.bi-status--paid { background: #e7f8ee; color: #135f31; }
.bi-status--open, .bi-status--uncollectible { background: #fde2e2; color: #7a1612; }
.bi-link { font-size: 13px; font-weight: 700; color: var(--brand-primary, #2563eb); text-decoration: none; white-space: nowrap; }
.bi-link:hover { text-decoration: underline; }
.billing-invoices .link-btn { background: none; border: 0; padding: 0; color: var(--brand-primary, #2563eb); font: inherit; cursor: pointer; text-decoration: underline; }

/* Public legal pages (Terms / Privacy) */
.legal-page { max-width: 760px; margin: 0 auto; padding: 36px 24px 80px; color: #1f2937; line-height: 1.65; }
.legal-page h1 { font-size: 30px; font-weight: 800; margin: 4px 0 2px; color: #0f172a; }
.legal-page h2 { font-size: 18px; font-weight: 700; margin: 26px 0 6px; color: #0f172a; }
.legal-page p, .legal-page li { font-size: 15px; }
.legal-page ul { padding-left: 20px; margin: 6px 0; }
.legal-page li { margin: 4px 0; }
.legal-page a { color: var(--brand-primary, #2563eb); }
.legal-updated { color: #64748b; font-size: 13px; margin: 0 0 18px; }
.legal-back { display: inline-block; font-size: 13px; font-weight: 600; color: #64748b; text-decoration: none; margin-bottom: 8px; }
.legal-back:hover { color: var(--brand-primary, #2563eb); }
.legal-foot { margin-top: 32px; padding-top: 16px; border-top: 1px solid #e5e7eb; font-size: 13px; color: #64748b; }
/* Login consent line */
.login-legal { margin-top: 14px; text-align: center; font-size: 12px; color: #94a3b8; }
.login-legal a { color: #94a3b8; text-decoration: underline; }

/* 3-tier paywall (Individual / Team / Association) */
.paywall-cad { display: inline-flex; gap: 0; background: #f1f5f9; border-radius: 999px; padding: 4px; margin: 2px auto 18px; }
.paywall-cad-btn { border: 0; background: transparent; padding: 7px 16px; border-radius: 999px; font-weight: 700; font-size: 13px; color: #475569; cursor: pointer; }
.paywall-cad-btn.active { background: #fff; color: #0f172a; box-shadow: 0 1px 2px rgba(0,0,0,.08); }
.paywall-tiers { display: grid; grid-template-columns: repeat(3, 1fr); gap: 12px; text-align: left; }
.paywall-tier { position: relative; border: 1px solid #e5e7eb; border-radius: 14px; padding: 18px 16px; display: flex; flex-direction: column; gap: 8px; background: #fff; }
.paywall-tier--featured { border-color: var(--brand-primary, #2563eb); box-shadow: 0 0 0 1px var(--brand-primary, #2563eb); }
.pt-badge { position: absolute; top: -10px; left: 16px; background: var(--brand-primary, #2563eb); color: #fff; font-size: 10px; font-weight: 800; letter-spacing: .04em; text-transform: uppercase; padding: 3px 8px; border-radius: 999px; }
.pt-name { font-size: 12px; font-weight: 800; letter-spacing: .03em; text-transform: uppercase; color: #64748b; }
.pt-price { font-size: 28px; font-weight: 800; color: #0f172a; line-height: 1; }
.pt-per { font-size: 14px; font-weight: 600; color: #64748b; }
.pt-desc { font-size: 13px; color: #475569; line-height: 1.45; flex: 1; }
.pt-cta { width: 100%; margin-top: 6px; }
@media (max-width: 640px) { .paywall-tiers { grid-template-columns: 1fr; } }

/* Association (club) subscription card */
.assoc-billing-card h3 { margin: 0 0 6px; }
.assoc-bill-controls { display: flex; flex-wrap: wrap; align-items: center; gap: 10px; margin-top: 10px; }
.assoc-bill-controls .paywall-cad { margin: 0; }
.assoc-tier-sel { padding: 8px 11px; border: 1px solid #e5e7eb; border-radius: 8px; font-size: 14px; background: #fff; font-weight: 600; }
.assoc-bill-active { font-size: 15px; margin-bottom: 2px; }

/* ============================================================
   ACCOUNT PAGE
   ============================================================ */
.page-account .account-form {
  display: grid;
  gap: 12px;
  max-width: 480px;
}
.page-account .field input {
  width: 100%;
  padding: 10px 12px;
  border: 1px solid var(--border);
  border-radius: 8px;
  font-size: 14px;
  background: #fff;
}
.page-account .field input:focus {
  outline: none;
  border-color: var(--blue, #2864c8);
  box-shadow: 0 0 0 2px rgba(40,100,200,0.15);
}
.page-account .readonly-field {
  padding: 10px 12px;
  border: 1px solid var(--border-soft);
  border-radius: 8px;
  background: var(--bg-soft);
  color: var(--text-dim);
  font-size: 14px;
}
.page-account .account-actions {
  display: flex;
  align-items: center;
  gap: 12px;
  margin-top: 6px;
}
.page-account .account-msg {
  font-size: 13px;
  min-height: 18px;
}
.page-account .account-msg--ok  { color: var(--green, #1f9e5a); }
.page-account .account-msg--err { color: var(--danger, #dc2626); }
.page-account .account-danger { border-color: #f5b8b8; }
.page-account .account-danger .btn:hover { background: #fde2e2; color: #7a1612; }

/* Preference rows on the Account page — used for the dark-mode toggle. */
.page-account .pref-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  cursor: pointer;
}
.page-account .pref-row > span:first-child { flex: 1; min-width: 0; }
/* Toggle-switch styling for a plain checkbox. WebKit lets us appearance:none
 * and roll our own without bringing in a dependency. */
.page-account .pref-switch {
  appearance: none;
  -webkit-appearance: none;
  width: 44px;
  height: 24px;
  border-radius: 999px;
  background: var(--border);
  position: relative;
  cursor: pointer;
  transition: background .15s;
  flex-shrink: 0;
  margin: 0;
}
.page-account .pref-switch::after {
  content: '';
  position: absolute;
  top: 2px; left: 2px;
  width: 20px; height: 20px;
  border-radius: 50%;
  background: #ffffff;
  transition: left .15s;
  box-shadow: 0 1px 2px rgba(0,0,0,.2);
}
.page-account .pref-switch:checked { background: var(--brand-primary, #7c5cff); }
.page-account .pref-switch:checked::after { left: 22px; }

/* ============================================================
   SCHEDULE REDESIGN (route /games) — 2026-05-21
   ============================================================
   Stats strip + new schedule-table styling matching the mockup at
   ~/Downloads/app-schedule-light.html. Scoped to body.route-schedule
   so existing .data-table styles elsewhere are unaffected. Uses
   existing CSS vars (--bg-soft, --border, --text, etc.) where it
   can so dark mode picks up automatically; introduces a few new
   accent vars locally for the W/L/T pills and the "ice" blue. */
body.route-schedule,
body.route-roster {
  --rb-ice:      #1e6fbf;
  --rb-ice-soft: rgba(30, 111, 191, 0.06);
  --rb-ice-glow: rgba(30, 111, 191, 0.12);
  --rb-mint:     #22a06b;
  --rb-mint-soft:rgba(34, 160, 107, 0.10);
  --rb-loss:     #d94929;
  --rb-loss-soft:rgba(217, 73, 41, 0.08);
  --rb-warm:     #e89043;
  --rb-warm-soft:rgba(232, 144, 67, 0.10);
  /* Legacy schedule-specific aliases — earlier .schedule-* rules
   * reference --sched-* tokens. Keep them mapped to the shared
   * --rb-* palette so a renaming pass can happen separately. */
  --sched-ice:      var(--rb-ice);
  --sched-ice-soft: var(--rb-ice-soft);
  --sched-ice-glow: var(--rb-ice-glow);
  --sched-mint:     var(--rb-mint);
  --sched-mint-soft:var(--rb-mint-soft);
  --sched-loss:     var(--rb-loss);
  --sched-loss-soft:var(--rb-loss-soft);
  --sched-warm:     var(--rb-warm);
  --sched-warm-soft:var(--rb-warm-soft);
}
html.dark-mode body.route-schedule,
html.dark-mode body.route-roster {
  --rb-ice-soft: rgba(30, 111, 191, 0.14);
  --rb-ice-glow: rgba(30, 111, 191, 0.22);
  --rb-mint-soft:rgba(34, 160, 107, 0.18);
  --rb-loss-soft:rgba(217, 73, 41, 0.16);
  --rb-warm-soft:rgba(232, 144, 67, 0.16);
}

/* Stats strip */
body.route-schedule .stats-strip, body.route-roster .stats-strip {
  /* Four plain figures in a row — no cards, icons, rails or shadows. */
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: 0;
  margin: 4px 0 28px;
  border-top: 1px solid var(--border);
  border-bottom: 1px solid var(--border);
}
body.route-schedule .stat-card, body.route-roster .stat-card {
  padding: 14px 18px 14px 0;
  margin-right: 18px;
  border-right: 1px solid var(--border);
  background: transparent;
  min-width: 0;
}
body.route-schedule .stat-card:last-child, body.route-roster .stat-card:last-child { border-right: 0; margin-right: 0; }
body.route-schedule .stat-card-label, body.route-roster .stat-card-label {
  font-size: 13px;
  font-weight: 500;
  color: var(--text-dim);
  margin-bottom: 6px;
}
body.route-schedule .stat-card-label svg, body.route-roster .stat-card-label svg { display: none; }
body.route-schedule .stat-card-value, body.route-roster .stat-card-value {
  font-size: 22px;
  font-weight: 600;
  line-height: 1.2;
  color: var(--text);
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
body.route-schedule .stat-card-value em, body.route-roster .stat-card-value em {
  font-style: normal;
  font-weight: 500;
  font-size: 15px;
  color: var(--text-dim);
  margin-left: 5px;
}
body.route-schedule .stat-card-sub, body.route-roster .stat-card-sub {
  font-size: 13px;
  color: var(--text-dim);
  margin-top: 3px;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
body.route-schedule .stat-card-sub .up, body.route-roster .stat-card-sub .up { color: var(--sched-mint); }
body.route-schedule .stat-card-sub .down, body.route-roster .stat-card-sub .down { color: var(--sched-loss); }

/* Schedule table card */
body.route-schedule .table-card, body.route-roster .table-card {
  background: var(--bg);
  border: 1px solid var(--border);
  border-radius: 10px;
  overflow: hidden;
  margin-bottom: 24px;
}
body.route-schedule .table-card .card-head, body.route-roster .table-card .card-head {
  padding: 24px 24px 20px;
  border-bottom: none;
}
body.route-schedule .schedule-table {
  width: 100%;
  border-collapse: collapse;
}
body.route-schedule .schedule-table thead {
  background: var(--bg-soft);
  border-top: 1px solid var(--border);
  border-bottom: 1px solid var(--border);
}
body.route-schedule .schedule-table th {
  font-family: inherit;
  font-size: 12px;
  font-weight: 600;
  color: var(--text-dim);
  text-align: left;
  padding: 12px 16px;
  white-space: nowrap;
}
body.route-schedule .schedule-table th:first-child { padding-left: 24px; }
body.route-schedule .schedule-table th:last-child { padding-right: 24px; text-align: right; }
body.route-schedule .schedule-table tbody tr {
  border-bottom: 1px solid var(--border-soft);
  transition: background-color .12s;
}
body.route-schedule .schedule-table tbody tr:last-child { border-bottom: none; }
body.route-schedule .schedule-table tbody tr:hover { background: var(--bg-soft); }
body.route-schedule .schedule-table tbody tr.upcoming-row {
  background: var(--sched-ice-soft);
  border-left: 3px solid var(--sched-ice);
}
body.route-schedule .schedule-table td {
  padding: 16px;
  font-size: 14px;
  vertical-align: middle;
  color: var(--text);
}
body.route-schedule .schedule-table td:first-child { padding-left: 24px; }
body.route-schedule .schedule-table td:last-child { padding-right: 24px; text-align: right; }

/* Date cell */
body.route-schedule .date-cell { display: flex; align-items: center; gap: 12px; }
body.route-schedule .date-cell .date-icon {
  width: 32px; height: 32px;
  border-radius: 8px;
  background: var(--sched-ice-soft);
  border: 1px solid var(--sched-ice-glow);
  display: flex; align-items: center; justify-content: center;
  color: var(--sched-ice);
  flex-shrink: 0;
}
body.route-schedule .date-cell .date-icon svg { width: 14px; height: 14px; }
body.route-schedule .date-cell .date-text { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
body.route-schedule .date-cell .date-main {
  font-family: inherit;
  font-size: 13px;
  font-weight: 500;
  color: var(--text);
}
body.route-schedule .date-cell .date-day {
  font-family: inherit;
  font-size: 12px;
  color: var(--text-dim);
}
body.route-schedule .status-dot {
  display: inline-block;
  width: 6px; height: 6px;
  border-radius: 50%;
  margin-right: 6px;
}
body.route-schedule .status-dot.upcoming { background: var(--sched-ice); }
body.route-schedule .status-dot.completed { background: var(--text-dim); }

body.route-schedule .time-cell {
  font-family: inherit;
  font-size: 13px;
  color: var(--text);
  font-weight: 500;
}

body.route-schedule .opponent-cell {
  display: flex;
  flex-direction: column;
  gap: 2px;
  min-width: 0;
}
body.route-schedule .opponent-cell .opponent-name {
  font-family: 'Instrument Sans', 'Geist', sans-serif;
  font-size: 15px;
  font-weight: 600;
  letter-spacing: -0.015em;
  color: var(--text);
}
body.route-schedule .opponent-cell .opponent-venue {
  font-size: 12px;
  color: var(--text-dim);
}

/* H/A badge */
body.route-schedule .ha-badge {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 32px; height: 24px;
  border-radius: 6px;
  font-family: inherit;
  font-size: 11px;
  font-weight: 600;
}
body.route-schedule .ha-badge.home {
  background: var(--sched-ice-soft);
  color: var(--sched-ice);
  border: 1px solid var(--sched-ice-glow);
}
body.route-schedule .ha-badge.away {
  background: var(--sched-loss-soft);
  color: var(--sched-loss);
  border: 1px solid rgba(217, 73, 41, 0.2);
}

/* Score */
body.route-schedule .score-cell {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  font-family: inherit;
  font-size: 15px;
  font-weight: 600;
}
body.route-schedule .score-cell .score-dash { color: var(--text-dim); }
body.route-schedule .score-cell.loss .score-our { color: var(--text-dim); }
body.route-schedule .score-cell.unplayed { color: var(--text-dim); font-weight: 500; }

/* Result badge */
body.route-schedule .result-badge {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 28px;
  height: 24px;
  padding: 0 8px;
  border-radius: 6px;
  font-family: inherit;
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.05em;
}
body.route-schedule .result-badge.w {
  background: var(--sched-mint-soft);
  color: var(--sched-mint);
  border: 1px solid rgba(34, 160, 107, 0.3);
}
body.route-schedule .result-badge.l {
  background: var(--sched-loss-soft);
  color: var(--sched-loss);
  border: 1px solid rgba(217, 73, 41, 0.25);
}
body.route-schedule .result-badge.t {
  background: var(--sched-warm-soft);
  color: var(--sched-warm);
  border: 1px solid rgba(232, 144, 67, 0.3);
}
body.route-schedule .result-empty {
  color: var(--text-dim);
  font-family: inherit;
  font-size: 14px;
}

/* Action buttons */
body.route-schedule .actions-cell, body.route-roster .actions-cell {
  display: flex;
  gap: 6px;
  justify-content: flex-end;
  align-items: center;
  flex-wrap: wrap;
}
body.route-schedule .action-btn, body.route-roster .action-btn {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 6px 10px;
  background: var(--bg);
  border: 1px solid var(--border);
  border-radius: 6px;
  color: var(--text-dim);
  font-family: inherit;
  font-size: 12px;
  cursor: pointer;
  transition: background-color .12s, border-color .12s, color .12s;
  font-weight: 500;
}
body.route-schedule .action-btn:hover, body.route-roster .action-btn:hover {
  background: var(--bg-soft);
  color: var(--text);
}
body.route-schedule .action-btn svg, body.route-roster .action-btn svg { width: 12px; height: 12px; }
body.route-schedule .action-btn.primary, body.route-roster .action-btn.primary {
  color: var(--sched-ice);
  border-color: rgba(30, 111, 191, 0.3);
  background: var(--sched-ice-soft);
  font-weight: 600;
}
body.route-schedule .action-btn.primary:hover, body.route-roster .action-btn.primary:hover {
  background: var(--sched-ice-glow);
  border-color: var(--sched-ice);
}

/* Mobile */
@media (max-width: 1024px) {
  body.route-schedule .stats-strip, body.route-roster .stats-strip { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  body.route-schedule .stat-card:nth-child(2), body.route-roster .stat-card:nth-child(2) { border-right: 0; }
  body.route-schedule .schedule-table th:nth-child(4),
  body.route-schedule .schedule-table td:nth-child(4),
  body.route-schedule .schedule-table th:nth-child(5),
  body.route-schedule .schedule-table td:nth-child(5) { display: none; }
}
@media (max-width: 640px) {
  body.route-schedule .stats-strip, body.route-roster .stats-strip { grid-template-columns: 1fr; }
  body.route-schedule .stat-card, body.route-roster .stat-card { border-right: 0; margin-right: 0; border-bottom: 1px solid var(--border); }
  body.route-schedule .stat-card:last-child, body.route-roster .stat-card:last-child { border-bottom: 0; }
  body.route-schedule .schedule-table th:nth-child(6),
  body.route-schedule .schedule-table td:nth-child(6) { display: none; }
}

/* Phone: the schedule table becomes stacked cards — every column (score,
   result, actions) stays reachable instead of clipping off-screen. */
@media (max-width: 700px) {
  body.route-schedule .schedule-table thead { display: none; }
  body.route-schedule .schedule-table,
  body.route-schedule .schedule-table tbody { display: block; width: 100%; }
  body.route-schedule .schedule-table tbody tr {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 4px 10px;
    padding: 14px 16px;
  }
  body.route-schedule .schedule-table td {
    display: block;
    padding: 0;
    border: 0;
  }
  body.route-schedule .schedule-table td:first-child { padding-left: 0; }
  body.route-schedule .schedule-table td:last-child { padding-right: 0; }
  body.route-schedule .schedule-table td:nth-child(1) { order: 1; flex: 1 1 auto; }
  body.route-schedule .schedule-table td:nth-child(2) { order: 2; color: var(--text-dim); font-weight: 600; font-size: 13px; }
  body.route-schedule .schedule-table td:nth-child(3) { order: 3; flex: 1 1 100%; margin-top: 2px; }
  /* Bring the H/A, score, result chips BACK (wider breakpoints hide them). */
  body.route-schedule .schedule-table td:nth-child(4),
  body.route-schedule .schedule-table td:nth-child(5),
  body.route-schedule .schedule-table td:nth-child(6) {
    display: inline-flex;
    align-items: center;
    order: 4;
  }
  body.route-schedule .schedule-table td:nth-child(7) {
    order: 5;
    flex: 1 1 100%;
    margin-top: 8px;
    text-align: left;
  }
  body.route-schedule .actions-cell {
    flex-wrap: wrap;
    justify-content: flex-start;
  }
  /* Practices / events have no H-A, score, or result — drop the dash chips. */
  body.route-schedule .schedule-table tr.row-practice td:nth-child(4),
  body.route-schedule .schedule-table tr.row-practice td:nth-child(5),
  body.route-schedule .schedule-table tr.row-practice td:nth-child(6),
  body.route-schedule .schedule-table tr.row-event td:nth-child(4),
  body.route-schedule .schedule-table tr.row-event td:nth-child(5),
  body.route-schedule .schedule-table tr.row-event td:nth-child(6) { display: none; }
}

/* ============================================================
   iPad toolbar scroll — explicit max-height so overflow engages
   ============================================================
   The base .toolbar uses overflow-y: auto + min-height: 0, which works
   on desktop Safari/Chrome but iOS Safari doesn't reliably pin the
   grid-item to its cell height, so the toolbar grows to fit content
   and there's nothing to scroll. Explicit max-height forces the
   issue — once the box is a fixed size, overflow-y: auto produces a
   real scroll region.
   The calc reserves room for: topnav 52 + topbar ~48 + drill-tabs 34
   + ~8 padding = ~142px of chrome above the toolbar. Uses dvh so iOS
   Safari's URL-bar-aware viewport height is honoured (vh would over-
   shoot when the URL bar is visible).
*/
@media (max-width: 1366px) {
  body.route-drill .toolbar {
    max-height: calc(100vh - 142px);   /* fallback for pre-dvh iOS */
  }
}
@supports (height: 100dvh) {
  @media (max-width: 1366px) {
    body.route-drill .toolbar {
      max-height: calc(100dvh - 142px);
    }
  }
}

/* ============================================================
   ROSTER REDESIGN (route /roster) — 2026-05-21
   ============================================================
   Shares the --rb-* palette and the stats-strip/table-card/action-btn
   primitives with the schedule. Adds roster-specific bits: a jersey
   disc on each row (colour matches the player's position group),
   a position pill, and a star-rating preview. */
body.route-roster .roster-group { padding: 0; }
body.route-roster .roster-group + .roster-group {
  border-top: 1px solid var(--border-soft);
}
body.route-roster .roster-group-head {
  display: flex;
  align-items: baseline;
  gap: 10px;
  padding: 18px 24px 10px;
  font-family: 'Instrument Sans', 'Geist', sans-serif;
  font-size: 18px;
  font-weight: 500;
  letter-spacing: -0.02em;
  color: var(--text);
}
/* Duplicate jersey number — amber ring on the tile's number disc. */
.lu-num--dupe {
  box-shadow: 0 0 0 2px #d97706;
}
body.route-roster .roster-group-head .count {
  font-family: inherit;
  font-size: 11px;
  font-weight: 600;
  color: var(--text-dim);
}

body.route-roster .roster-table {
  width: 100%;
  border-collapse: collapse;
}
body.route-roster .roster-table tbody tr {
  border-top: 1px solid var(--border-soft);
  transition: background-color .12s;
}
body.route-roster .roster-table tbody tr:hover { background: var(--bg-soft); }
body.route-roster .roster-table td {
  padding: 14px 16px;
  font-size: 14px;
  vertical-align: middle;
  color: var(--text);
}
body.route-roster .roster-table td:first-child { padding-left: 24px; }
body.route-roster .roster-table td:last-child { padding-right: 24px; text-align: right; }

/* Jersey disc — number in a coloured circle. Colour comes from the
 * player's position group via .pos-fwd / .pos-def / .pos-gk. */
body.route-roster .jersey-disc {
  width: 36px; height: 36px;
  border-radius: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
  font-family: inherit;
  font-size: 14px;
  font-weight: 700;
  color: #fff;
  flex-shrink: 0;
  background: var(--text-dim);
}
body.route-roster .jersey-disc.pos-fwd { background: var(--rb-ice); }
body.route-roster .jersey-disc.pos-def { background: var(--rb-loss); }
body.route-roster .jersey-disc.pos-gk  { background: var(--rb-mint); }
body.route-roster .jersey-disc.no-number {
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.04em;
}

/* Player name cell — same visual rhythm as the schedule's opponent-cell. */
body.route-roster .player-cell {
  display: flex;
  align-items: center;
  gap: 12px;
  min-width: 0;
}
body.route-roster .player-cell .player-text {
  display: flex;
  flex-direction: column;
  gap: 2px;
  min-width: 0;
}
body.route-roster .player-cell .player-name {
  font-family: 'Instrument Sans', 'Geist', sans-serif;
  font-size: 15px;
  font-weight: 600;
  letter-spacing: -0.015em;
  color: var(--text);
}
body.route-roster .player-cell .player-sub {
  font-family: inherit;
  font-size: 11px;
  color: var(--text-dim);
}

/* Position pill — small badge in the position-group colour. */
body.route-roster .pos-pill {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 36px;
  height: 22px;
  padding: 0 8px;
  border-radius: 6px;
  font-family: inherit;
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.04em;
}
body.route-roster .pos-pill.pos-fwd {
  background: var(--rb-ice-soft);
  color: var(--rb-ice);
  border: 1px solid var(--rb-ice-glow);
}
body.route-roster .pos-pill.pos-def {
  background: var(--rb-loss-soft);
  color: var(--rb-loss);
  border: 1px solid rgba(217, 73, 41, 0.2);
}
body.route-roster .pos-pill.pos-gk {
  background: var(--rb-mint-soft);
  color: var(--rb-mint);
  border: 1px solid rgba(34, 160, 107, 0.3);
}
body.route-roster .pos-pill.pos-none {
  background: var(--bg-soft);
  color: var(--text-dim);
  border: 1px solid var(--border-soft);
}

/* Shoots badge — single-char L/R indicator. */
body.route-roster .shoots-badge {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 22px; height: 22px;
  border-radius: 5px;
  font-family: inherit;
  font-size: 11px;
  font-weight: 700;
  background: var(--bg-soft);
  color: var(--text);
  border: 1px solid var(--border-soft);
}
body.route-roster .shoots-empty {
  color: var(--text-dim);
  font-family: inherit;
  font-size: 13px;
}

/* Star-rating preview — average across categories shown as 5 stars +
 * numeric. Filled stars warm-orange, empty stars border-grey. */
body.route-roster .star-row {
  display: inline-flex;
  align-items: center;
  gap: 6px;
}
body.route-roster .star-row .stars {
  display: inline-flex;
  gap: 1px;
  color: var(--rb-warm);
}
body.route-roster .star-row svg { width: 12px; height: 12px; }
body.route-roster .star-row svg.empty { color: var(--border); }
body.route-roster .star-row .rating-num {
  font-family: inherit;
  font-size: 11px;
  color: var(--text-dim);
}
body.route-roster .star-row.empty {
  font-family: inherit;
  font-size: 12px;
  color: var(--text-dim);
}

/* Search input inside the roster table header */
/* Player count chip beside the "Team Roster" title. */
body.route-roster .roster-count {
  font: 600 14px/1 Geist, system-ui, sans-serif;
  color: var(--text-dim);
  margin-left: 8px;
  vertical-align: middle;
}
body.route-roster .page-actions { align-items: center; }

body.route-roster .roster-search {
  position: relative;
  display: inline-flex;
  align-items: center;
}
body.route-roster .roster-search svg {
  position: absolute;
  left: 10px;
  width: 14px; height: 14px;
  color: var(--text-dim);
  pointer-events: none;
}
body.route-roster .roster-search input {
  background: var(--bg-soft);
  border: 1px solid var(--border-soft);
  border-radius: 8px;
  padding: 8px 12px 8px 32px;
  font-family: inherit;
  font-size: 13px;
  color: var(--text);
  width: 240px;
  transition: border-color .15s, background-color .15s;
}
body.route-roster .roster-search input:focus {
  outline: none;
  border-color: var(--rb-ice);
  background: var(--bg);
  box-shadow: 0 0 0 3px var(--rb-ice-soft);
}

/* Mobile: hide ratings + shoots so the row stays readable */
@media (max-width: 1024px) {
  body.route-roster .roster-table th:nth-child(4),
  body.route-roster .roster-table td:nth-child(4),
  body.route-roster .roster-table th:nth-child(5),
  body.route-roster .roster-table td:nth-child(5) { display: none; }
}

/* ============================================================
   /admin/ads — platform-admin sponsor CRUD. Two-column layout:
   list of ads on the left, inline edit drawer on the right.
   ============================================================ */
body.route-admin-ads .admin-ads-layout {
  display: grid;
  grid-template-columns: 1fr 460px;
  gap: 24px;
  align-items: start;
}
@media (max-width: 1100px) {
  body.route-admin-ads .admin-ads-layout { grid-template-columns: 1fr; }
}
body.route-admin-ads .admin-ads-list {
  display: flex;
  flex-direction: column;
  gap: 8px;
}
body.route-admin-ads .admin-ads-empty {
  padding: 48px 20px;
  border: 1px dashed var(--border-soft);
  border-radius: 14px;
  text-align: center;
  color: var(--text-dim);
}
body.route-admin-ads .admin-ads-row {
  appearance: none;
  background: white;
  border: 1px solid var(--border-soft);
  border-radius: 12px;
  padding: 12px 16px;
  display: flex;
  align-items: center;
  gap: 14px;
  text-align: left;
  cursor: pointer;
  font-family: inherit;
  transition: background .12s, border-color .12s, transform .12s;
}
body.route-admin-ads .admin-ads-row:hover {
  background: var(--bg-soft);
  border-color: var(--border);
}
body.route-admin-ads .admin-ads-row-logo {
  width: 48px;
  height: 32px;
  display: flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
  background: var(--bg-soft);
  border-radius: 6px;
  overflow: hidden;
}
body.route-admin-ads .admin-ads-row-logo img {
  max-width: 100%;
  max-height: 100%;
  object-fit: contain;
}
body.route-admin-ads .admin-ads-row-main { flex: 1; min-width: 0; }
body.route-admin-ads .admin-ads-row-name {
  font-size: 14px;
  font-weight: 600;
  color: var(--text);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
body.route-admin-ads .admin-ads-row-meta {
  font-size: 12px;
  color: var(--text-dim);
  margin-top: 2px;
}
body.route-admin-ads .admin-ads-pill {
  font-size: 11px;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.4px;
  background: var(--bg-soft);
  color: var(--text-dim);
  padding: 3px 9px;
  border-radius: 999px;
}
body.route-admin-ads .admin-ads-pill--on {
  background: color-mix(in srgb, var(--brand-secondary) 14%, white);
  color: color-mix(in srgb, var(--brand-secondary) 80%, #000);
}
body.route-admin-ads .admin-ads-edit {
  position: sticky;
  top: 24px;
  background: white;
  border: 1px solid var(--border-soft);
  border-radius: 14px;
  padding: 20px;
}
@media (max-width: 1100px) {
  body.route-admin-ads .admin-ads-edit { position: static; }
}
body.route-admin-ads .admin-ads-edit-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: 16px;
}
body.route-admin-ads .admin-ads-edit-head h2 { margin: 0; font-size: 17px; }
body.route-admin-ads .admin-ads-edit .field { display: block; margin-bottom: 12px; }
body.route-admin-ads .admin-ads-edit .field > span {
  display: block;
  font-size: 11.5px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.5px;
  color: var(--text-dim);
  margin-bottom: 4px;
}
body.route-admin-ads .admin-ads-edit .field input,
body.route-admin-ads .admin-ads-edit .field select {
  width: 100%;
  padding: 9px 11px;
  border: 1px solid var(--border-soft);
  border-radius: 8px;
  font-size: 13.5px;
  font-family: inherit;
  background: white;
  color: var(--text);
}
body.route-admin-ads .admin-ads-edit .field input:focus,
body.route-admin-ads .admin-ads-edit .field select:focus {
  outline: none;
  border-color: var(--brand-secondary);
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--brand-secondary) 12%, transparent);
}
body.route-admin-ads .admin-ads-edit .field-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 10px;
}
body.route-admin-ads .admin-ads-actions {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-top: 18px;
  padding-top: 14px;
  border-top: 1px solid var(--border-soft);
}
body.route-admin-ads .admin-ads-actions .btn-danger {
  background: var(--red);
  color: white;
  border: none;
}

/* Logo upload — preview swatch on the left, buttons + hint on the
   right, external-URL paste-in below. Both feed the same hidden
   #ad-logo field (the canonical submitted value). */
body.route-admin-ads .admin-ads-logo-row {
  display: flex;
  align-items: center;
  gap: 14px;
  margin-bottom: 8px;
}
body.route-admin-ads .admin-ads-logo-preview {
  flex-shrink: 0;
  width: 88px;
  height: 56px;
  border: 1px solid var(--border-soft);
  border-radius: 8px;
  background:
    repeating-conic-gradient(#f3f4f6 0% 25%, #ffffff 0% 50%) 0 0 / 12px 12px;
  display: flex;
  align-items: center;
  justify-content: center;
  overflow: hidden;
}
body.route-admin-ads .admin-ads-logo-preview img {
  max-width: 100%;
  max-height: 100%;
  object-fit: contain;
}
body.route-admin-ads .admin-ads-logo-placeholder {
  font-size: 11px;
  color: var(--text-dim);
}
body.route-admin-ads .admin-ads-logo-controls {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 6px;
}
body.route-admin-ads .admin-ads-logo-controls .btn {
  padding: 6px 12px;
  font-size: 12.5px;
}
body.route-admin-ads .admin-ads-logo-hint {
  font-size: 11px;
  color: var(--text-dim);
}

/* Aggregate stats baked into each list row (lifetime totals). */
body.route-admin-ads .admin-ads-row-stats {
  display: flex;
  gap: 10px;
  font-size: 11.5px;
  color: var(--text-dim);
  margin-top: 6px;
}

/* Edit-drawer performance panel. */
body.route-admin-ads .admin-ads-stats {
  margin-top: 18px;
  padding-top: 14px;
  border-top: 1px solid var(--border-soft);
}
body.route-admin-ads .admin-ads-stats-head {
  font-size: 11.5px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.5px;
  color: var(--text-dim);
  margin-bottom: 10px;
}
body.route-admin-ads .admin-ads-stats-totals {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 10px;
  margin-bottom: 14px;
}
body.route-admin-ads .admin-ads-stat {
  background: var(--bg-soft);
  border-radius: 8px;
  padding: 10px 12px;
  text-align: left;
}
body.route-admin-ads .admin-ads-stat-n {
  font-size: 18px;
  font-weight: 700;
  color: var(--text);
  line-height: 1.1;
}
body.route-admin-ads .admin-ads-stat-l {
  font-size: 11px;
  color: var(--text-dim);
  margin-top: 2px;
  text-transform: uppercase;
  letter-spacing: 0.5px;
}
body.route-admin-ads .admin-ads-stats-chart {
  display: flex;
  align-items: flex-end;
  gap: 3px;
  height: 70px;
  margin-bottom: 6px;
  overflow-x: auto;
}
body.route-admin-ads .admin-ads-bar {
  position: relative;
  flex: 1 0 14px;
  min-width: 14px;
  max-width: 28px;
  height: 100%;
  display: flex;
  flex-direction: column-reverse;
  align-items: stretch;
  border-radius: 3px 3px 0 0;
  background: linear-gradient(to top, var(--bg-soft) 0%, var(--bg-soft) 100%);
}
body.route-admin-ads .admin-ads-bar-imp {
  width: 100%;
  background: color-mix(in srgb, var(--brand-secondary) 30%, white);
  border-radius: 3px 3px 0 0;
  min-height: 1px;
}
body.route-admin-ads .admin-ads-bar-clk {
  width: 100%;
  background: var(--brand-secondary);
  border-radius: 3px 3px 0 0;
  position: absolute;
  bottom: 0;
  left: 0;
  min-height: 1px;
}
body.route-admin-ads .admin-ads-bar-day {
  position: absolute;
  bottom: -16px;
  left: 0;
  right: 0;
  font-size: 9px;
  color: var(--text-dim);
  text-align: center;
  line-height: 1;
}
body.route-admin-ads .admin-ads-stats-sub {
  margin-top: 18px;
  font-size: 11px;
  color: var(--text-dim);
}
body.route-admin-ads .admin-ads-stats-empty {
  width: 100%;
  text-align: center;
  font-size: 12px;
  color: var(--text-dim);
  padding: 18px;
}

/* ============================================================
   "Powered by" sponsor pill — shared across every placement.
   Slot wrappers position the pill; .pc-ad styles the pill itself.
   Slot is empty (zero height) until ads.js fills it; that prevents
   layout shift when there's nothing to render for a team.
   2026-05-26.
   ============================================================ */
.pc-ad-slot {
  /* Empty until populated — the .pc-ad-slot--filled class is added by
     ads.js once an ad lands so we don't bake in vertical space for
     teams in regions with no inventory. */
  min-height: 0;
}
.pc-ad-slot--filled {
  /* Just enough padding for the pill to breathe without crowding the
     surrounding UI. Page-specific placements can override. */
  padding: 6px 0;
}
/* Base .pc-ad — neutral layout + transitions. Colors come from the
   on-light / on-dark variants below; ads.js stamps the appropriate
   class on the slot after reading the effective background luminance.
   This keeps the pill legible whether it sits on a white dashboard
   card or a team-branded topbar in literally any colour the coach
   has picked. */
.pc-ad {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 6px 14px;
  border: 1px solid transparent;
  border-radius: 999px;
  font-size: 12.5px;
  text-decoration: none;
  transition: background .15s, border-color .15s, transform .15s, color .15s;
  font-family: inherit;
  white-space: nowrap;
  max-width: 100%;
  overflow: hidden;
}
.pc-ad:hover { transform: translateY(-1px); }
.pc-ad-label {
  font-weight: 500;
  font-size: 11px;
  text-transform: uppercase;
  letter-spacing: 0.5px;
  flex-shrink: 0;
}
.pc-ad-logo {
  height: 20px;
  width: auto;
  max-width: 80px;
  object-fit: contain;
  flex-shrink: 0;
}
.pc-ad-sponsor {
  font-weight: 600;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* Light-background variant — dark text reads on white-ish surfaces
   like the dashboard hero, share page, and any light card. This is
   the default until JS finishes the contrast check; default avoids a
   flash-of-invisible text on the common case (most pages are light). */
.pc-ad-slot--on-light .pc-ad,
.pc-ad-slot:not(.pc-ad-slot--on-dark) .pc-ad {
  background: rgba(255, 255, 255, 0.78);
  border-color: var(--border-soft);
  color: var(--text);
}
.pc-ad-slot--on-light .pc-ad:hover,
.pc-ad-slot:not(.pc-ad-slot--on-dark) .pc-ad:hover {
  background: white;
  border-color: var(--border);
}
.pc-ad-slot--on-light .pc-ad-label,
.pc-ad-slot:not(.pc-ad-slot--on-dark) .pc-ad-label {
  color: var(--text-dim);
}
.pc-ad-slot--on-light .pc-ad-sponsor,
.pc-ad-slot:not(.pc-ad-slot--on-dark) .pc-ad-sponsor {
  color: var(--text);
}

/* Dark-background variant — light text. Activated when the slot's
   computed background is dark (luminance < 0.55), e.g. the drill
   board topbar's team panel_color. Pill background stays mostly
   transparent so the team brand colour shows through. */
.pc-ad-slot--on-dark .pc-ad {
  background: rgba(255, 255, 255, 0.08);
  border-color: rgba(255, 255, 255, 0.18);
  color: rgba(255, 255, 255, 0.92);
}
.pc-ad-slot--on-dark .pc-ad:hover {
  background: rgba(255, 255, 255, 0.16);
  border-color: rgba(255, 255, 255, 0.32);
}
.pc-ad-slot--on-dark .pc-ad-label { color: rgba(255, 255, 255, 0.6); }
.pc-ad-slot--on-dark .pc-ad-sponsor { color: white; }

/* Dashboard slot: centered between the hero and the widget grid. */
.dash-sponsor.pc-ad-slot--filled {
  display: flex;
  justify-content: center;
  margin: 8px 0 16px;
}

/* Share page slot: centered under the share card. */
.share-sponsor.pc-ad-slot--filled {
  display: flex;
  justify-content: center;
  margin-top: 24px;
}

/* Drill board slot — compact sizing inside the dense topbar; colors
   are inherited from whichever on-light/on-dark variant ads.js picks. */
#ad-slot-drillboard.pc-ad-slot--filled {
  padding: 0;
  display: flex;
  align-items: center;
}
#ad-slot-drillboard .pc-ad {
  padding: 4px 10px;
  font-size: 11.5px;
}
#ad-slot-drillboard .pc-ad-logo { height: 16px; }

/* ============================================================
   Plans v3 — bookshelf of clipboard-style plan cards.
   2026-05-26. Replaces the old `.plan-card` grid (which is still
   styled higher up in this file and used by the editor sidebar /
   PDF preview — leave those rules alone).
   ============================================================ */

/* Toolbar (search + book filter chips + sort) */
.plans-page .plans-toolbar {
  display: flex;
  flex-direction: column;
  gap: 12px;
  margin-bottom: 22px;
}
.plans-page .plans-search {
  position: relative;
}
.plans-page .plans-search input {
  width: 100%;
  padding: 11px 14px 11px 42px;
  border: 1px solid var(--border-soft);
  border-radius: 10px;
  background: white;
  font-size: 14.5px;
  font-family: inherit;
  color: var(--text);
  outline: none;
  transition: border-color .12s, box-shadow .12s;
}
.plans-page .plans-search input:focus {
  border-color: var(--brand-secondary);
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--brand-secondary) 12%, transparent);
}
.plans-page .plans-search-icon {
  position: absolute;
  left: 14px;
  top: 50%;
  transform: translateY(-50%);
  width: 17px;
  height: 17px;
  color: var(--text-dim);
  pointer-events: none;
}
.plans-page .plans-toolbar-row {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
}
.plans-page .plans-book-filters {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
}
.plans-page .plans-book-chip {
  padding: 6px 12px;
  border: 1px solid var(--border-soft);
  background: white;
  color: var(--text);
  border-radius: 999px;
  font-size: 12.5px;
  font-weight: 600;
  cursor: pointer;
  font-family: inherit;
  display: inline-flex;
  align-items: center;
  gap: 6px;
  transition: background .12s, border-color .12s, color .12s;
}
.plans-page .plans-book-chip:hover {
  background: var(--bg-soft);
  border-color: var(--border);
}
.plans-page .plans-book-chip.is-active {
  background: var(--brand-secondary);
  border-color: var(--brand-secondary);
  color: white;
}
.plans-page .plans-book-chip-count {
  font-size: 10.5px;
  font-weight: 700;
  background: var(--bg-soft);
  color: var(--text-dim);
  padding: 1px 7px;
  border-radius: 999px;
  min-width: 20px;
  text-align: center;
}
.plans-page .plans-book-chip.is-active .plans-book-chip-count {
  background: rgba(255, 255, 255, 0.22);
  color: white;
}
.plans-page .plans-sort {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  font-size: 11.5px;
  color: var(--text-dim);
  flex-shrink: 0;
}
.plans-page .plans-sort-label {
  text-transform: uppercase;
  font-weight: 700;
  letter-spacing: 0.6px;
}
.plans-page .plans-sort-select {
  padding: 7px 10px;
  border: 1px solid var(--border-soft);
  border-radius: 8px;
  background: white;
  font-size: 13px;
  color: var(--text);
  cursor: pointer;
  font-family: inherit;
}

/* Override the legacy `#plan-grid` (which was a CSS grid for the old
   .plan-card layout). Plans v3 lays shelves out as a vertical stack, so
   we need plain block flow here. */
.plans-page #plan-grid {
  display: block;
}

/* Bookshelf — each `.plans-shelf` is one book worth of clipboards. */
.plans-shelf {
  margin-bottom: 36px;
  position: relative;
}
.plans-shelf-head {
  display: flex;
  align-items: baseline;
  gap: 14px;
  margin-bottom: 18px;
}
.plans-shelf-title {
  font-size: 18px;
  font-weight: 700;
  color: var(--text);
  margin: 0;
  letter-spacing: -0.005em;
}
.plans-shelf-count {
  font-size: 12px;
  color: var(--text-dim);
  font-weight: 600;
}
.plans-shelf-row {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
  gap: 24px 18px;
  align-items: end;
}
/* The "shelf floor" — a thin horizontal rule below each row that
   suggests a physical shelf without going full wood-grain. Subtle
   gradient hints at depth so the clipboards feel like they're
   resting on something. */
.plans-shelf-floor {
  height: 6px;
  margin-top: 14px;
  background: linear-gradient(
    180deg,
    color-mix(in srgb, var(--text-dim) 35%, transparent) 0%,
    color-mix(in srgb, var(--text-dim) 14%, transparent) 35%,
    transparent 100%
  );
  border-radius: 3px 3px 0 0;
}

/* The clipboard — paper-feeling card with a clip detail at the top
   and the first drill's thumbnail as the cover. Skeuomorphic but
   restrained: no wood-grain background, no 3D clip, just enough
   metaphor for a hockey coach to recognise. */
.plan-clip {
  position: relative;
  display: flex;
  flex-direction: column;
  background: #fbfaf6;             /* off-white paper tone */
  border: 1px solid #d8d5cc;       /* subtle paper edge */
  border-radius: 4px 4px 8px 8px;  /* sharper top, rounded bottom */
  padding-top: 22px;               /* space for the clip band */
  cursor: pointer;
  box-shadow: 0 4px 0 -2px #d8d5cc,
              0 8px 18px -8px rgba(0, 0, 0, 0.18);
  transition: transform .15s ease, box-shadow .15s ease;
  outline: none;
}
.plan-clip:hover {
  transform: translateY(-3px);
  box-shadow: 0 6px 0 -2px #d8d5cc,
              0 16px 28px -10px rgba(0, 0, 0, 0.22);
}
.plan-clip:focus-visible {
  border-color: var(--brand-secondary);
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--brand-secondary) 22%, transparent),
              0 6px 0 -2px #d8d5cc,
              0 16px 28px -10px rgba(0, 0, 0, 0.22);
}

/* Top band — the metal/paper clip. A thin gradient strip with a
   small notch in the centre. Reads as a clip without the cartoonish
   3D dome of the MyDrillBook clipboards. */
.plan-clip-top {
  position: absolute;
  top: -6px;
  left: 0;
  right: 0;
  height: 18px;
  display: flex;
  justify-content: center;
  pointer-events: none;
  z-index: 2;
}
.plan-clip-clip {
  width: 64px;
  height: 18px;
  background: linear-gradient(
    180deg,
    #cfd2d8 0%, #aaaeb6 40%, #898d96 70%, #6f7380 100%
  );
  border-radius: 4px;
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.55),
    inset 0 -1px 0 rgba(0, 0, 0, 0.18),
    0 2px 4px -1px rgba(0, 0, 0, 0.3);
  position: relative;
}
.plan-clip-clip::after {
  /* The pin-hole / spring detail in the middle of the clip */
  content: '';
  position: absolute;
  left: 50%; top: 50%;
  transform: translate(-50%, -50%);
  width: 8px; height: 8px;
  background: #4d505b;
  border-radius: 50%;
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.18);
}

/* The "page" — text-centric clipboard surface. Plan title is the
   dominant element; age + drill count + total min sit below; a small
   abstract hockey diagram sits at the bottom as decoration (not a
   thumbnail of the actual drill — coaches asked for the
   MyDrillBook-style generic graphic instead). */
.plan-clip-page {
  position: relative;
  margin: 0 8px;
  aspect-ratio: 16 / 13;     /* tall-ish so the title has room */
  background: white;
  border: 1px solid #e9e7df;
  border-radius: 3px;
  overflow: hidden;
  display: flex;
  flex-direction: column;
  padding: 14px 14px 0;
}
.plan-clip-page-title {
  display: flex;
  align-items: flex-start;
  gap: 6px;
  font-size: 14px;
  font-weight: 700;
  line-height: 1.22;
  color: var(--text);
  letter-spacing: -0.005em;
  /* Two-line clamp so titles stay readable even when long. */
  overflow: hidden;
  text-overflow: ellipsis;
  display: -webkit-box;
  -webkit-line-clamp: 3;
  -webkit-box-orient: vertical;
}
.plan-clip-page-title > span {
  overflow: hidden;
  text-overflow: ellipsis;
  display: -webkit-box;
  -webkit-line-clamp: 3;
  -webkit-box-orient: vertical;
}
.plan-clip-page-meta {
  margin-top: 6px;
  font-size: 11.5px;
  color: var(--text-dim);
  font-weight: 600;
  letter-spacing: 0.2px;
}
.plan-clip-page-diagram {
  margin-top: auto;          /* pin to bottom of the page */
  padding-top: 8px;
  opacity: 0.78;
}
.plan-clip-page-diagram svg {
  width: 100%;
  height: auto;
  display: block;
}
.plan-clip-upcoming {
  position: absolute;
  top: 8px;
  left: 8px;
  background: var(--green, #1f9e5a);
  color: white;
  font-size: 10.5px;
  font-weight: 700;
  padding: 3px 8px 3px 6px;
  border-radius: 999px;
  display: inline-flex;
  align-items: center;
  gap: 4px;
  letter-spacing: 0.3px;
}
.plan-clip-upcoming svg { width: 11px; height: 11px; }

/* Hover-revealed action overlay on the page. Run is the primary
   action and gets brand red; share + delete are neutral. */
.plan-clip-actions {
  position: absolute;
  bottom: 8px;
  right: 8px;
  display: flex;
  gap: 6px;
  opacity: 0;
  transition: opacity .15s;
}
.plan-clip:hover .plan-clip-actions,
.plan-clip:focus-within .plan-clip-actions {
  opacity: 1;
}
.plan-clip-action {
  width: 30px;
  height: 30px;
  border-radius: 50%;
  border: none;
  background: rgba(255, 255, 255, 0.95);
  color: var(--text);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  box-shadow: 0 2px 6px rgba(0, 0, 0, 0.18);
  transition: transform .12s, background .12s, color .12s;
}
.plan-clip-action:hover { transform: scale(1.06); }
.plan-clip-action svg { width: 14px; height: 14px; }
.plan-clip-action--run { background: var(--red, #7c5cff); color: white; }
.plan-clip-action--del:hover { background: var(--danger, #dc2626); color: white; }

/* Footer — date / book context. Only rendered when one is present;
   plan name + age + drill count live ON the page above. */
.plan-clip-foot {
  padding: 10px 12px 12px;
}
.plan-clip-meta {
  font-size: 11.5px;
  color: var(--text-dim);
  line-height: 1.4;
}
.plan-clip-dot {
  width: 8px;
  height: 8px;
  border-radius: 50%;
  flex-shrink: 0;
}
.plan-clip-dot--visible { background: var(--brand-secondary, #1e6fbf); }
.plan-clip-dot--private { background: #b59500; }

/* Upcoming plans get a subtle green hint on the paper edge */
.plan-clip--upcoming {
  border-color: color-mix(in srgb, var(--green, #1f9e5a) 50%, #d8d5cc);
}
.plan-clip--shared {
  border-color: color-mix(in srgb, var(--brand-secondary, #1e6fbf) 35%, #d8d5cc);
}

/* Mobile / narrow viewport — clipboards shrink, shelves keep their
   rhythm but rows allow wrapping. */
@media (max-width: 720px) {
  .plans-shelf-row {
    grid-template-columns: repeat(auto-fill, minmax(150px, 1fr));
    gap: 18px 12px;
  }
  .plan-clip-foot { padding: 10px 10px 12px; }
  .plan-clip-title { font-size: 13px; }
  .plan-clip-meta { font-size: 11px; }
}

/* ============================================================
   /vault — coach-facing browse for platform-curated content.
   Phase 1: drills only. Card design borrows from /library/drills
   but adds claim affordances + featured/popular badges.
   2026-05-26.
   ============================================================ */
body.route-vault .vault-toolbar {
  display: flex;
  flex-direction: column;
  gap: 12px;
  margin-bottom: 24px;
}
body.route-vault .vault-search {
  position: relative;
}
body.route-vault .vault-search input {
  width: 100%;
  padding: 11px 14px 11px 42px;
  border: 1px solid var(--border-soft);
  border-radius: 10px;
  background: white;
  font-size: 14.5px;
  font-family: inherit;
  color: var(--text);
  outline: none;
  transition: border-color .12s, box-shadow .12s;
}
body.route-vault .vault-search input:focus {
  border-color: var(--brand-secondary);
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--brand-secondary) 12%, transparent);
}
body.route-vault .vault-search-icon {
  position: absolute;
  left: 14px;
  top: 50%;
  transform: translateY(-50%);
  width: 17px;
  height: 17px;
  color: var(--text-dim);
  pointer-events: none;
}
body.route-vault .vault-filter-row {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
}
body.route-vault .vault-chips {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
}
body.route-vault .vault-chip {
  padding: 6px 12px;
  border: 1px solid var(--border-soft);
  background: white;
  color: var(--text);
  border-radius: 999px;
  font-size: 12.5px;
  font-weight: 600;
  cursor: pointer;
  font-family: inherit;
  transition: background .12s, border-color .12s, color .12s;
}
body.route-vault .vault-chip:hover {
  background: var(--bg-soft);
  border-color: var(--border);
}
body.route-vault .vault-chip.is-active {
  background: var(--brand-secondary);
  border-color: var(--brand-secondary);
  color: white;
}
body.route-vault .vault-sort {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  font-size: 11.5px;
  color: var(--text-dim);
}
body.route-vault .vault-sort-label {
  text-transform: uppercase;
  font-weight: 700;
  letter-spacing: 0.6px;
}
body.route-vault .vault-sort-select {
  padding: 7px 10px;
  border: 1px solid var(--border-soft);
  border-radius: 8px;
  background: white;
  font-size: 13px;
  color: var(--text);
  cursor: pointer;
  font-family: inherit;
}

body.route-vault .vault-section { margin-bottom: 36px; }
body.route-vault .vault-section-head {
  display: flex;
  align-items: baseline;
  gap: 12px;
  margin-bottom: 16px;
}
body.route-vault .vault-section-title {
  font-size: 17px;
  font-weight: 700;
  margin: 0;
  color: var(--text);
}
body.route-vault .vault-section-sub {
  font-size: 12px;
  color: var(--text-dim);
  font-weight: 500;
}
body.route-vault .vault-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(220px, 1fr));
  gap: 18px;
}
body.route-vault .vault-card {
  appearance: none;
  background: white;
  border: 1px solid var(--border-soft);
  border-radius: 14px;
  overflow: hidden;
  text-align: left;
  cursor: pointer;
  display: flex;
  flex-direction: column;
  padding: 0;
  font-family: inherit;
  transition: box-shadow .15s, transform .15s, border-color .15s;
}
body.route-vault .vault-card:hover {
  box-shadow: 0 14px 32px -14px rgba(0, 0, 0, 0.16);
  transform: translateY(-2px);
  border-color: var(--border);
}
body.route-vault .vault-card.is-claimed {
  border-color: color-mix(in srgb, var(--brand-secondary) 50%, var(--border-soft));
}
body.route-vault .vault-card-thumb {
  position: relative;
  aspect-ratio: 16 / 10;
  background: var(--bg-soft);
  overflow: hidden;
}
body.route-vault .vault-card-thumb img {
  width: 100%;
  height: 100%;
  object-fit: contain;
  display: block;
}
body.route-vault .vault-card-thumb--empty {
  display: flex;
  align-items: center;
  justify-content: center;
  color: var(--text-dim);
  font-size: 11px;
}
body.route-vault .vault-card-featured {
  position: absolute;
  top: 8px;
  left: 8px;
  width: 26px;
  height: 26px;
  border-radius: 999px;
  background: #ffd64a;
  color: #5a4400;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  font-size: 14px;
  box-shadow: 0 2px 6px rgba(0, 0, 0, 0.15);
}
body.route-vault .vault-card-claimed {
  position: absolute;
  bottom: 8px;
  right: 8px;
  font-size: 10.5px;
  font-weight: 700;
  letter-spacing: 0.4px;
  background: var(--brand-secondary);
  color: white;
  padding: 3px 8px;
  border-radius: 999px;
  text-transform: uppercase;
}
body.route-vault .vault-card-body {
  padding: 12px 14px 14px;
  display: flex;
  flex-direction: column;
  gap: 4px;
  flex: 1;
}
body.route-vault .vault-card-name {
  font-size: 14px;
  font-weight: 600;
  color: var(--text);
  line-height: 1.3;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
body.route-vault .vault-card-ages {
  font-size: 11.5px;
  color: var(--text-dim);
  font-weight: 600;
}
body.route-vault .vault-card-tags {
  display: flex;
  flex-wrap: wrap;
  gap: 4px;
  margin-top: 2px;
}
body.route-vault .vault-card-tag {
  background: color-mix(in srgb, var(--brand-secondary) 12%, white);
  color: color-mix(in srgb, var(--brand-secondary) 80%, #000);
  padding: 2px 8px;
  border-radius: 999px;
  font-size: 10.5px;
  font-weight: 500;
}
body.route-vault .vault-card-claimcount {
  font-size: 11px;
  color: var(--text-dim);
  margin-top: 4px;
}

body.route-vault .vault-tag-chips {
  margin-top: 10px;
}
body.route-vault .vault-carousel-wrap {
  position: relative;
}
body.route-vault .vault-carousel {
  display: flex;
  gap: 18px;
  overflow-x: auto;
  scroll-snap-type: x mandatory;
  padding-bottom: 6px;
  scrollbar-width: thin;
  -webkit-overflow-scrolling: touch;
}
body.route-vault .vault-carousel > * {
  flex: 0 0 236px;
  scroll-snap-align: start;
}
body.route-vault .vault-car-arrow {
  position: absolute;
  top: 50%;
  transform: translateY(-50%);
  z-index: 5;
  width: 38px;
  height: 38px;
  padding: 0;
  border-radius: 50%;
  border: 1px solid var(--border-soft);
  background: white;
  color: var(--brand-primary);
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  box-shadow: 0 2px 10px rgba(15, 23, 42, .14);
  transition: border-color .15s, box-shadow .15s;
}
body.route-vault .vault-car-arrow:hover {
  border-color: var(--brand-primary);
  box-shadow: 0 4px 14px rgba(15, 23, 42, .18);
}
body.route-vault .vault-car-arrow svg {
  width: 20px;
  height: 20px;
}
body.route-vault .vault-car-arrow[hidden] { display: none; }
body.route-vault .vault-car-arrow--prev { left: 8px; }
body.route-vault .vault-car-arrow--next { right: 8px; }
@media (max-width: 640px) {
  body.route-vault .vault-car-arrow { display: none; }
}
body.route-vault .vault-loadmore {
  display: flex;
  justify-content: center;
  padding: 18px 0 6px;
}
body.route-vault .vault-empty {
  text-align: center;
  padding: 60px 20px;
  color: var(--text-dim);
}
body.route-vault .vault-empty-icon { font-size: 40px; margin-bottom: 12px; }
body.route-vault .vault-empty-title { font-size: 16px; font-weight: 600; color: var(--text); margin-bottom: 4px; }
body.route-vault .vault-empty-sub   { font-size: 13px; }

/* Detail modal */
.vault-modal { display: none; }
.vault-modal:not([hidden]) { display: grid; place-items: center; }
.vault-modal-card {
  width: 600px;
  max-width: 92vw;
  max-height: 88vh;
  overflow-y: auto;
  position: relative;
}
.vault-modal-close {
  position: absolute;
  top: 10px; right: 14px;
  background: none;
  border: none;
  font-size: 28px;
  color: var(--text-dim);
  cursor: pointer;
  line-height: 1;
}
.vault-modal-close:hover { color: var(--text); }
.vault-modal-thumb {
  width: 100%;
  max-height: 360px;
  object-fit: contain;
  background: var(--bg-soft);
  border-radius: 10px;
  margin-bottom: 14px;
}
.vault-modal-name { margin: 6px 0 4px !important; }
.vault-modal-meta {
  font-size: 12.5px;
  color: var(--text-dim);
  font-weight: 600;
}
.vault-modal-desc {
  margin-top: 14px;
  font-size: 13.5px;
  color: var(--text);
  line-height: 1.5;
}
.vault-modal-actions {
  margin-top: 22px;
  display: flex;
  flex-direction: column;
  align-items: stretch;
  gap: 12px;
}
.vault-modal-actions .btn,
.vault-modal-actions .btn-primary {
  align-self: flex-end;
}
.vault-claim-options {
  display: flex;
  flex-direction: column;
  gap: 8px;
  padding: 14px 16px;
  background: color-mix(in srgb, var(--brand-secondary) 7%, white);
  border: 1px solid color-mix(in srgb, var(--brand-secondary) 18%, transparent);
  border-radius: 10px;
}
.vault-claim-opt {
  display: flex;
  align-items: center;
  gap: 10px;
  font-size: 13.5px;
  color: var(--text);
  cursor: pointer;
}
.vault-claim-opt input[type="checkbox"] {
  width: 16px; height: 16px;
  accent-color: var(--brand-secondary);
  cursor: pointer;
}
.vault-claim-opt.is-disabled {
  color: var(--text-dim);
  cursor: not-allowed;
}
.vault-claim-opt.is-disabled input { cursor: not-allowed; }
body.route-vault .vault-card-claimed--team {
  background: color-mix(in srgb, var(--brand-primary, #1f5fff) 80%, #000);
}
body.route-vault .vault-card-claimed--both {
  background: linear-gradient(135deg,
    var(--brand-secondary) 0 50%,
    color-mix(in srgb, var(--brand-primary, #1f5fff) 80%, #000) 50% 100%);
}
.vault-modal-loading,
.vault-modal-error {
  padding: 30px;
  text-align: center;
  color: var(--text-dim);
}

/* Type tabs (Drills | Plans) — shared by /vault and /admin/vault */
body.route-vault .vault-type-tabs,
body.route-admin-vault .vault-type-tabs {
  display: flex;
  gap: 4px;
  margin: -8px 0 18px;
  border-bottom: 1px solid var(--border, #e5e5ea);
  padding-bottom: 0;
}
body.route-vault .vault-type-tab,
body.route-admin-vault .vault-type-tab {
  appearance: none;
  background: none;
  border: none;
  border-bottom: 3px solid transparent;
  padding: 12px 18px 11px;
  font-size: 14px;
  font-weight: 600;
  color: var(--text-dim);
  cursor: pointer;
  margin-bottom: -1px;
  display: inline-flex;
  align-items: center;
  gap: 8px;
  transition: color 120ms, border-color 120ms;
}
body.route-vault .vault-type-tab:hover,
body.route-admin-vault .vault-type-tab:hover {
  color: var(--text);
}
body.route-vault .vault-type-tab.is-active,
body.route-admin-vault .vault-type-tab.is-active {
  color: var(--brand-secondary);
  border-bottom-color: var(--brand-secondary);
}
body.route-vault .vault-type-count,
body.route-admin-vault .vault-type-count {
  font-size: 11.5px;
  padding: 2px 7px;
  border-radius: 999px;
  background: color-mix(in srgb, var(--brand-secondary) 10%, transparent);
  color: var(--text-dim);
  min-width: 18px;
  text-align: center;
}
body.route-vault .vault-type-tab.is-active .vault-type-count,
body.route-admin-vault .vault-type-tab.is-active .vault-type-count {
  background: var(--brand-secondary);
  color: white;
}

/* Plan card — text-first clipboard look */
body.route-vault .vault-plan-card .vault-plan-clip {
  background: linear-gradient(180deg, #fff 0%, #fafaf6 100%);
  border: 1px solid color-mix(in srgb, var(--brand-secondary) 22%, #d8d4c4);
  border-top: 6px solid color-mix(in srgb, var(--brand-secondary) 70%, #b8a050);
  padding: 30px 16px 14px;
  display: flex;
  flex-direction: column;
  gap: 8px;
  position: relative;
  min-height: 170px;
  border-radius: 6px 6px 0 0;
}
/* Push the featured ★ out to the corner so it doesn't overlap the eyebrow. */
body.route-vault .vault-plan-card .vault-card-featured {
  top: 12px;
  left: 12px;
  position: absolute;
  z-index: 2;
}
body.route-vault .vault-plan-clip-head {
  display: flex;
  justify-content: space-between;
  align-items: flex-start;
  gap: 8px;
  padding-left: 30px;
}
body.route-vault .vault-plan-clip-eyebrow {
  font-size: 10px;
  font-weight: 800;
  letter-spacing: 1px;
  text-transform: uppercase;
  color: color-mix(in srgb, var(--brand-secondary) 75%, #000);
}
body.route-vault .vault-plan-clip-age {
  font-size: 11px;
  font-weight: 700;
  color: var(--text-dim);
  background: color-mix(in srgb, var(--brand-secondary) 8%, white);
  padding: 2px 8px;
  border-radius: 999px;
}
body.route-vault .vault-plan-clip-name {
  font-size: 17px;
  font-weight: 700;
  line-height: 1.25;
  color: var(--text);
  margin-top: 2px;
}
body.route-vault .vault-plan-clip-meta {
  font-size: 12px;
  color: var(--text-dim);
  font-weight: 600;
  margin-top: auto;
  padding-top: 8px;
}

/* Plan detail modal: drill list */
.vault-plan-drills {
  margin-top: 18px;
  display: flex;
  flex-direction: column;
  gap: 8px;
  border-top: 1px solid var(--border, #e5e5ea);
  padding-top: 14px;
}
.vault-plan-drill {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 6px 4px;
}
.vault-plan-drill-num {
  width: 22px; height: 22px;
  border-radius: 999px;
  background: color-mix(in srgb, var(--brand-secondary) 14%, white);
  color: color-mix(in srgb, var(--brand-secondary) 85%, #000);
  font-size: 11px;
  font-weight: 700;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex: 0 0 auto;
}
.vault-plan-drill-thumb {
  width: 64px; height: 40px;
  object-fit: cover;
  border-radius: 4px;
  background: var(--bg-soft);
}
.vault-plan-drill-thumb--empty {
  background: repeating-linear-gradient(45deg, #f0eee5, #f0eee5 6px, #e8e6dc 6px, #e8e6dc 12px);
}
.vault-plan-drill-meta { flex: 1; min-width: 0; }
.vault-plan-drill-name {
  font-size: 13.5px;
  font-weight: 600;
  color: var(--text);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.vault-plan-drill-sub {
  font-size: 11.5px;
  color: var(--text-dim);
}
.vault-modal-notes {
  margin-top: 14px;
  padding: 12px 14px;
  background: color-mix(in srgb, var(--brand-secondary) 6%, white);
  border-left: 3px solid var(--brand-secondary);
  border-radius: 4px;
  font-size: 13px;
  color: var(--text);
  line-height: 1.5;
}
.vault-modal-notes strong {
  display: block;
  font-size: 11px;
  letter-spacing: 0.6px;
  text-transform: uppercase;
  color: var(--text-dim);
  margin-bottom: 4px;
}
.vault-claim-opt-readonly {
  font-size: 13px;
  color: var(--text);
  padding: 4px 0 4px;
}

/* --- Loading states ------------------------------------------ */
/* Single keyframe powers skeletons + per-card thumb spinner. */
@keyframes vault-pulse {
  0%   { opacity: 0.55; }
  50%  { opacity: 1; }
  100% { opacity: 0.55; }
}
@keyframes vault-spin {
  to { transform: rotate(360deg); }
}

/* Skeleton card (gridded placeholder while we wait for /list to return) */
body.route-vault .vault-card-skeleton {
  pointer-events: none;
  cursor: default;
  background: var(--card-bg, white);
  border: 1px solid var(--border, #e5e5ea);
  border-radius: 10px;
  overflow: hidden;
  display: flex;
  flex-direction: column;
}
body.route-vault .vault-card-skeleton .vault-skel-thumb {
  aspect-ratio: 16 / 10;
  background: linear-gradient(90deg, #ececec 0%, #f5f5f5 50%, #ececec 100%);
  background-size: 200% 100%;
  animation: vault-skel-shimmer 1.4s ease-in-out infinite;
}
body.route-vault .vault-card-skeleton.vault-plan-card .vault-skel-thumb {
  /* Plan cards don't have a thumb area — substitute a tall block */
  aspect-ratio: 16 / 9;
}
body.route-vault .vault-skel-line {
  height: 10px;
  border-radius: 6px;
  background: linear-gradient(90deg, #ececec 0%, #f5f5f5 50%, #ececec 100%);
  background-size: 200% 100%;
  animation: vault-skel-shimmer 1.4s ease-in-out infinite;
  margin: 6px 0;
}
body.route-vault .vault-skel-line--name { width: 75%; height: 14px; }
body.route-vault .vault-skel-line--meta { width: 50%; }
@keyframes vault-skel-shimmer {
  0%   { background-position: 200% 0; }
  100% { background-position: -200% 0; }
}

/* Per-card thumb spinner — visible while the batched /thumbs request
 * is in flight. The <img> is hidden until its src is set. */
body.route-vault .vault-card-thumb--loading .vault-card-thumb-img {
  display: none;
}
body.route-vault .vault-card-thumb-spinner {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  background: repeating-linear-gradient(45deg, #f4f4f0, #f4f4f0 8px, #ececec 8px, #ececec 16px);
  background-size: 22px 22px;
  animation: vault-pulse 1.2s ease-in-out infinite;
}
body.route-vault .vault-card-thumb-spinner::after {
  content: '';
  width: 22px; height: 22px;
  border-radius: 50%;
  border: 2.5px solid color-mix(in srgb, var(--brand-secondary) 28%, #e5e5ea);
  border-top-color: var(--brand-secondary);
  animation: vault-spin 0.85s linear infinite;
  background: white;
}
/* Once the image loads, the slot drops the loading class — hide spinner. */
body.route-vault .vault-card-thumb:not(.vault-card-thumb--loading) .vault-card-thumb-spinner {
  display: none;
}

/* Generic vault spinner (used in the detail modal "Loading…" state) */
.vault-spinner {
  width: 36px; height: 36px;
  border-radius: 50%;
  border: 3px solid color-mix(in srgb, var(--brand-secondary) 25%, #e5e5ea);
  border-top-color: var(--brand-secondary);
  animation: vault-spin 0.85s linear infinite;
  margin: 0 auto 12px;
}
.vault-modal-loading {
  padding: 40px 30px;
  text-align: center;
}
.vault-modal-loading-text {
  color: var(--text-dim);
  font-size: 13px;
}

/* --- /admin/vault curator page ------------------------------- */
body.route-admin-vault .av-toolbar {
  display: flex;
  gap: 12px;
  align-items: center;
  margin-bottom: 14px;
}
body.route-admin-vault #av-search {
  flex: 1;
  padding: 9px 12px;
  border: 1px solid var(--border, #e5e5ea);
  border-radius: 8px;
  font-size: 13.5px;
}
body.route-admin-vault .av-show-inactive {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-size: 13px;
  color: var(--text-dim);
  cursor: pointer;
}
body.route-admin-vault .av-list {
  display: flex;
  flex-direction: column;
  gap: 8px;
}
body.route-admin-vault .av-row {
  display: grid;
  grid-template-columns: 80px 1fr auto;
  gap: 14px;
  align-items: center;
  padding: 10px 12px;
  background: var(--card-bg, white);
  border: 1px solid var(--border, #e5e5ea);
  border-radius: 8px;
}
body.route-admin-vault .av-row.is-inactive { opacity: 0.55; }
body.route-admin-vault .av-row-thumb {
  width: 80px; height: 52px;
  object-fit: contain;
  background: var(--bg-soft, #f5f5f5);
  border-radius: 4px;
}
body.route-admin-vault .av-row-thumb--empty {
  background: repeating-linear-gradient(45deg, #f4f4f0, #f4f4f0 6px, #e8e6dc 6px, #e8e6dc 12px);
}
body.route-admin-vault .av-row-thumb--plan {
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 26px;
  background: color-mix(in srgb, var(--brand-secondary) 10%, #fafaf6);
}
body.route-admin-vault .av-row-main { min-width: 0; }
body.route-admin-vault .av-row-name {
  font-size: 14px;
  font-weight: 600;
  display: flex;
  align-items: center;
  gap: 6px;
}
body.route-admin-vault .av-featured-pin { color: #d4a700; }
body.route-admin-vault .av-deleted-pill {
  font-size: 10px;
  font-weight: 700;
  letter-spacing: 0.5px;
  background: #d33;
  color: white;
  padding: 2px 6px;
  border-radius: 4px;
  margin-left: 4px;
}
body.route-admin-vault .av-row-meta {
  font-size: 11.5px;
  color: var(--text-dim);
  margin-top: 2px;
}
body.route-admin-vault .av-row-tags {
  margin-top: 4px;
  display: flex;
  flex-wrap: wrap;
  gap: 4px;
}
body.route-admin-vault .av-tag {
  background: color-mix(in srgb, var(--brand-secondary) 12%, white);
  color: color-mix(in srgb, var(--brand-secondary) 80%, #000);
  padding: 2px 7px;
  border-radius: 999px;
  font-size: 10.5px;
}
body.route-admin-vault .av-row-actions {
  display: flex;
  gap: 6px;
  flex-shrink: 0;
}
body.route-admin-vault .av-empty {
  text-align: center;
  padding: 60px 20px;
  color: var(--text-dim);
}
body.route-admin-vault .av-empty-title { font-weight: 600; color: var(--text); margin-bottom: 4px; }

/* Edit form */
.av-form { display: flex; flex-direction: column; gap: 12px; margin-top: 14px; }
.av-field { display: flex; flex-direction: column; gap: 4px; }
.av-field > span {
  font-size: 11.5px;
  font-weight: 600;
  letter-spacing: 0.3px;
  text-transform: uppercase;
  color: var(--text-dim);
}
.av-field input[type="text"],
.av-field input[type="number"],
.av-field textarea {
  padding: 8px 10px;
  border: 1px solid var(--border, #e5e5ea);
  border-radius: 6px;
  font: inherit;
  width: 100%;
  box-sizing: border-box;
}
.av-field textarea { resize: vertical; }
.av-field-row { display: flex; gap: 12px; }
.av-field-half {
  flex: 1;
  display: flex;
  flex-direction: column;
  gap: 4px;
}
.av-field-half > span {
  font-size: 11.5px;
  font-weight: 600;
  letter-spacing: 0.3px;
  text-transform: uppercase;
  color: var(--text-dim);
}

/* Promote-to-Vault button (per-card on library / plans page).
 * Positioned absolutely in the bottom-left corner of the card so it
 * doesn't fight the existing fav-star (top-right) or animate-chip. */
.send-to-vault-btn {
  position: absolute;
  bottom: 6px;
  left: 6px;
  display: inline-flex;
  align-items: center;
  gap: 4px;
  padding: 3px 7px;
  font-size: 10px;
  font-weight: 700;
  letter-spacing: 0.4px;
  text-transform: uppercase;
  background: linear-gradient(135deg, #d4a700, #b8950a);
  color: white;
  border: none;
  border-radius: 4px;
  cursor: pointer;
  text-decoration: none;
  box-shadow: 0 1px 3px rgba(0,0,0,0.18);
  z-index: 5;
  opacity: 0;
  transform: translateY(4px);
  transition: opacity 120ms, transform 120ms;
}
/* Show on hover or when the card is already in the vault (so admins
 * can spot what's curated at a glance). */
.lib-card:hover .send-to-vault-btn,
.drill-card:hover .send-to-vault-btn,
.plan-clip:hover .send-to-vault-btn,
.send-to-vault-btn.is-in-vault,
.send-to-vault-btn:focus {
  opacity: 1;
  transform: translateY(0);
}
.send-to-vault-btn:hover { filter: brightness(1.08); }
.send-to-vault-btn.is-in-vault {
  background: linear-gradient(135deg, #2a8f3c, #1d7530);
  color: white;
}
/* On plan clips, the bottom-left has the "share/run/delete" action row.
 * Park the button at the top-right instead. */
.plan-clip .send-to-vault-btn {
  top: 8px;
  bottom: auto;
  left: auto;
  right: 8px;
}

/* Touch devices have no hover state — the reveal-on-hover pattern
 * makes Send-to-Vault and Revert buttons invisible on iPad/phone.
 * Force them visible when the primary pointer is coarse + no hover. */
@media (hover: none) and (pointer: coarse) {
  .send-to-vault-btn,
  .vault-revert-btn {
    opacity: 1;
    transform: none;
  }
}

/* "↩ Revert from Vault" button — appears on cards whose underlying
 * drill/plan was claimed from the Vault. Same hover-reveal pattern as
 * .send-to-vault-btn but positioned bottom-right so they don't fight. */
.vault-revert-btn {
  position: absolute;
  bottom: 6px;
  right: 6px;
  display: inline-flex;
  align-items: center;
  gap: 4px;
  padding: 3px 7px;
  font-size: 10px;
  font-weight: 700;
  letter-spacing: 0.4px;
  text-transform: uppercase;
  background: rgba(0, 0, 0, 0.75);
  color: white;
  border: none;
  border-radius: 4px;
  cursor: pointer;
  box-shadow: 0 1px 3px rgba(0,0,0,0.2);
  z-index: 5;
  opacity: 0;
  transform: translateY(4px);
  transition: opacity 120ms, transform 120ms;
}
.lib-card:hover .vault-revert-btn,
.drill-card:hover .vault-revert-btn,
.plan-clip:hover .vault-revert-btn,
.vault-revert-btn:focus {
  opacity: 1;
  transform: translateY(0);
}
.vault-revert-btn:hover { background: rgba(0, 0, 0, 0.9); }
/* Park the plan-clip revert button bottom-left so it doesn't fight the
 * existing share/run/delete action row at the bottom-right. */
.plan-clip .vault-revert-btn {
  bottom: 8px;
  right: auto;
  left: 8px;
}

/* Revert confirm modal — same Emil polish family as the corner-confirm modal. */
.vault-revert-modal { display: none; }
.vault-revert-modal:not([hidden]) {
  display: grid;
  place-items: center;
  transition: opacity 200ms ease-out;
}
@starting-style {
  .vault-revert-modal:not([hidden]) { opacity: 0; }
}
.vault-revert-card {
  width: 460px;
  max-width: 92vw;
  padding: 24px 26px;
  transform-origin: center;
  transition:
    transform 240ms cubic-bezier(0.23, 1, 0.32, 1),
    opacity 220ms ease-out;
}
@starting-style {
  .vault-revert-card { transform: scale(0.96); opacity: 0; }
}
.vault-revert-actions .btn {
  transition: transform 120ms ease-out, background 120ms ease-out;
}
.vault-revert-actions .btn:active {
  transform: scale(0.97);
}
@media (prefers-reduced-motion: reduce) {
  .vault-revert-modal:not([hidden]),
  .vault-revert-card { transition: opacity 180ms ease-out; transform: none; }
  .vault-revert-actions .btn:active { transform: none; }
}

/* --- Onboarding tour ------------------------------------------ */
/* Three-piece UI: full-screen overlay (dimmed), spotlight (a window
   through the overlay onto the highlighted element), and the floating
   card with copy + controls. The overlay + spotlight + card all fade
   together when the tour opens / closes / advances. */
.pc-tour {
  position: fixed;
  inset: 0;
  z-index: 5000;
  pointer-events: none;
  opacity: 0;
  visibility: hidden;
  transition:
    opacity 220ms ease-out,
    visibility 0s linear 220ms;
}
.pc-tour--open {
  opacity: 1;
  visibility: visible;
  pointer-events: auto;
  transition: opacity 220ms ease-out;
}
.pc-tour-overlay {
  position: absolute;
  inset: 0;
  background: rgba(15, 18, 22, 0.55);
  backdrop-filter: blur(1px);
  -webkit-backdrop-filter: blur(1px);
}
/* Spotlight uses a massive outset box-shadow as the dim layer — the
   element itself stays bright while everything around it is dark.
   Positions are mutated via inline style from JS as steps advance. */
.pc-tour-spotlight {
  position: absolute;
  border-radius: 10px;
  box-shadow: 0 0 0 9999px rgba(15, 18, 22, 0.62);
  pointer-events: none;
  /* Smooth glide between steps so the spotlight doesn't snap. */
  transition:
    left 320ms cubic-bezier(0.23, 1, 0.32, 1),
    top 320ms cubic-bezier(0.23, 1, 0.32, 1),
    width 320ms cubic-bezier(0.23, 1, 0.32, 1),
    height 320ms cubic-bezier(0.23, 1, 0.32, 1),
    opacity 200ms ease-out;
}
/* When there's no spotlight target, hide the dim layer above so the
   centered "Welcome" / "You're set" card sits over just the overlay. */
.pc-tour-spotlight[style*="opacity: 0"] { box-shadow: none; }

.pc-tour-card {
  position: absolute;
  width: 340px;
  max-width: calc(100vw - 36px);
  background: white;
  border-radius: 12px;
  padding: 22px 24px 18px;
  box-shadow: 0 18px 48px rgba(0,0,0,0.35);
  transition:
    left 320ms cubic-bezier(0.23, 1, 0.32, 1),
    top 320ms cubic-bezier(0.23, 1, 0.32, 1),
    opacity 200ms ease-out;
}
/* On phones, shrink padding + tighten the card so it doesn't dwarf the
   spotlight. The card still respects max-width: calc(100vw - 36px). */
@media (max-width: 480px) {
  .pc-tour-card {
    padding: 18px 18px 14px;
    width: calc(100vw - 36px);
  }
  .pc-tour-title { font-size: 16px; }
  .pc-tour-body { font-size: 13px; margin-bottom: 16px; }
}
.pc-tour-card[data-placement="center"] {
  transform: translate(-50%, -50%);
  transition:
    opacity 220ms ease-out,
    transform 280ms cubic-bezier(0.23, 1, 0.32, 1);
}
.pc-tour--open .pc-tour-card {
  /* No-op selector — keeps the linter happy and reserves space for
     future per-state tweaks. */
}
.pc-tour-step {
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 1.5px;
  text-transform: uppercase;
  color: var(--text-dim);
  margin-bottom: 8px;
}
.pc-tour-title {
  margin: 0 0 8px;
  font-size: 18px;
  font-weight: 700;
  color: var(--text);
  letter-spacing: -0.01em;
}
.pc-tour-body {
  margin: 0 0 20px;
  font-size: 13.5px;
  line-height: 1.55;
  color: var(--text);
}
.pc-tour-actions {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
}
.pc-tour-nav { display: flex; gap: 8px; }
.pc-tour-skip,
.pc-tour-back,
.pc-tour-next {
  border: none;
  font: inherit;
  font-weight: 600;
  font-size: 13px;
  cursor: pointer;
  padding: 8px 14px;
  border-radius: 6px;
  transition: background 140ms ease-out, transform 120ms ease-out, opacity 140ms ease-out;
}
.pc-tour-skip {
  background: transparent;
  color: var(--text-dim);
  padding-left: 4px;
  padding-right: 4px;
}
.pc-tour-skip:hover { color: var(--text); }
.pc-tour-back {
  background: transparent;
  color: var(--text-dim);
  border: 1px solid var(--border, #e5e5ea);
}
.pc-tour-back:hover { background: var(--bg-soft); color: var(--text); }
.pc-tour-back:disabled { opacity: 0.35; cursor: default; }
.pc-tour-next {
  background: var(--brand-secondary, #1f5fff);
  color: white;
  box-shadow: 0 1px 3px rgba(0,0,0,0.14);
}
.pc-tour-next:hover { filter: brightness(1.06); }
/* Emil press feedback on all three controls. */
.pc-tour-skip:active,
.pc-tour-back:not(:disabled):active,
.pc-tour-next:active { transform: scale(0.97); }
@media (prefers-reduced-motion: reduce) {
  .pc-tour,
  .pc-tour-spotlight,
  .pc-tour-card { transition: opacity 180ms ease-out; }
  .pc-tour-skip:active,
  .pc-tour-back:active,
  .pc-tour-next:active { transform: none; }
}

/* --- Drag-to-reorder library cards (#47) ----------------------
   Active only when activeSort === 'custom'. Cards get a subtle
   grab cursor + lift on hover; the dragged card dims; drop targets
   show a vertical accent bar on the side the cursor is on. */
.lib-card.is-draggable {
  cursor: grab;
  /* Prevent the browser from scrolling/zooming the page when the
     coach starts dragging on touch — the JS handles the gesture. */
  touch-action: none;
  -webkit-touch-callout: none;
  -webkit-user-select: none;
  user-select: none;
}
.lib-card.is-draggable:active { cursor: grabbing; }
.lib-card.lib-card--dragging {
  opacity: 0.4;
  /* No transform during drag — the browser handles the drag image. */
}
/* Drop indicator — vertical accent bar on the chosen side. */
.lib-card--drop-before,
.lib-card--drop-after {
  position: relative;
}
.lib-card--drop-before::before,
.lib-card--drop-after::after {
  content: '';
  position: absolute;
  top: 0;
  bottom: 0;
  width: 3px;
  background: var(--brand-secondary, #1f5fff);
  border-radius: 2px;
  /* Soft glow so the indicator pops even on busy backgrounds. */
  box-shadow: 0 0 0 1px rgba(255,255,255,0.6), 0 0 8px rgba(31,95,255,0.5);
  pointer-events: none;
}
.lib-card--drop-before::before { left: -5px; }
.lib-card--drop-after::after  { right: -5px; }
@media (prefers-reduced-motion: reduce) {
  .lib-card.lib-card--dragging { opacity: 0.5; }
}
.vault-revert-card h2 {
  font-size: 18px;
  margin: 0 0 12px;
}
.vault-revert-card p {
  font-size: 13.5px;
  line-height: 1.55;
  color: var(--text);
  margin: 0 0 10px;
}
.vault-revert-card .vault-revert-warn {
  font-size: 12.5px;
  color: var(--text-dim);
  background: color-mix(in srgb, var(--brand-secondary) 8%, white);
  border-left: 3px solid var(--brand-secondary);
  padding: 8px 12px;
  border-radius: 4px;
}
.vault-revert-actions {
  margin-top: 18px;
  display: flex;
  justify-content: flex-end;
  gap: 10px;
}

/* --- Manual corner-adjustment modal for image import ----------
   Emil polish: backdrop fades in via @starting-style; card scales up
   from 0.96 with a custom ease-out; handles stagger in 40ms apart so
   they read as a deliberate sequence rather than a script firing.
   The modal is added fresh to the DOM each open so @starting-style
   fires reliably; the polygon + handle attributes mutate during drag
   without re-rendering (see confirmRinkCorners in page_drill.js). */
.rink-corners-modal {
  display: grid;
  place-items: center;
  /* Backdrop fades 200ms when the element is added to the DOM. */
  background: rgba(20, 22, 26, 0.5);
  backdrop-filter: blur(2px);
  -webkit-backdrop-filter: blur(2px);
  transition: opacity 200ms ease-out;
}
@starting-style {
  .rink-corners-modal { opacity: 0; }
}
.rink-corners-card {
  width: 920px;
  max-width: 96vw;
  padding: 22px 24px;
  transform-origin: center; /* Modal exception: stays centered, not anchored to a trigger. */
  transition:
    transform 260ms cubic-bezier(0.23, 1, 0.32, 1),
    opacity 240ms ease-out;
}
@starting-style {
  .rink-corners-card {
    transform: scale(0.96);
    opacity: 0;
  }
}
.rink-corners-card h2 {
  margin: 0 0 8px;
  font-size: 18px;
}
.rink-corners-card p {
  margin: 0 0 14px;
  color: var(--text-dim);
  font-size: 13px;
  line-height: 1.5;
}
.rink-corners-canvas-wrap {
  /* Flex-center a shrink-wrapped frame so the SVG overlay can bind to the
     IMAGE's box, not the wrap's. The old layout (padding-top for labels +
     svg at top:0 sized from a mid-animation getBoundingClientRect) drew
     the corner frame 28px high and ~4% small — the model's corners were
     right but the yellow rails rendered offset. */
  display: flex;
  justify-content: center;
  max-height: 60vh;
  overflow: visible;
  border-radius: 6px;
}
.rink-corners-frame {
  position: relative;
  display: inline-block;
}
.rink-corners-img {
  display: block;
  max-width: 100%;
  max-height: 60vh;
  user-select: none;
  -webkit-user-drag: none;
}
.rink-corners-svg {
  /* Exactly cover the image, whatever its displayed size — no JS sizing.
     viewBox is the image's natural pixels, so pct math never touches
     layout rects. overflow visible lets the TL/TR labels poke above. */
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  overflow: visible;
  touch-action: none;
}
.rink-corner-poly {
  fill: rgba(212, 167, 0, 0.18);
  stroke: #d4a700;
  stroke-width: 2;
  pointer-events: none;
}
.rink-corner-handle {
  cursor: grab;
  /* Anchor scale at the handle's own center (it's translated by `transform`
     on the <g>; the visual scale here applies to its children). */
  transform-box: fill-box;
  transform-origin: center;
  /* Stagger entry — each handle's animation-delay set per :nth-of-type below.
     animation runs once, sets the final state. */
  animation: rink-corner-handle-in 220ms cubic-bezier(0.23, 1, 0.32, 1) both;
  /* The handle's own visual scale (separate from the translate on its <g>
     transform attribute, which we mutate during drag). */
  transition: scale 140ms ease-out;
}
.rink-corner-handle:active { cursor: grabbing; }
@keyframes rink-corner-handle-in {
  from { opacity: 0; scale: 0.6; }
  to   { opacity: 1; scale: 1; }
}
.rink-corner-handle:nth-of-type(1) { animation-delay: 60ms; }
.rink-corner-handle:nth-of-type(2) { animation-delay: 100ms; }
.rink-corner-handle:nth-of-type(3) { animation-delay: 140ms; }
.rink-corner-handle:nth-of-type(4) { animation-delay: 180ms; }
/* Touch devices fire fake hover on tap → gate the hover-scale so dragged
   handles don't stay scaled after a drag on iPad. */
@media (hover: hover) and (pointer: fine) {
  .rink-corner-handle:hover { scale: 1.08; }
}
.rink-corner-handle-bg {
  fill: rgba(212, 167, 0, 0.25);
  stroke: #d4a700;
  stroke-width: 2;
}
.rink-corner-handle-dot {
  fill: #d4a700;
  stroke: white;
  stroke-width: 2;
}
.rink-corner-handle-label {
  fill: white;
  font: bold 11px sans-serif;
  text-anchor: middle;
  paint-order: stroke;
  stroke: rgba(0,0,0,0.7);
  stroke-width: 3;
}
.rink-corners-actions {
  margin-top: 18px;
  display: flex;
  justify-content: flex-end;
  gap: 10px;
}
/* Universal button press feedback — Emil's rule: every pressable element
   must respond to press. 120ms is short enough to feel instant. */
.rink-corners-actions .btn {
  transition: transform 120ms ease-out, background 120ms ease-out;
}
.rink-corners-actions .btn:active {
  transform: scale(0.97);
}
@media (prefers-reduced-motion: reduce) {
  .rink-corners-modal,
  .rink-corners-card { transition: opacity 180ms ease-out; transform: none; }
  .rink-corner-handle { animation: none; opacity: 1; scale: 1; }
  .rink-corner-handle:hover { scale: 1; }
  .rink-corners-actions .btn:active { transform: none; }
}

/* ============================================================
   /dev/smoke — iPad regression checklist page
   ============================================================
   Big tap targets (44px+), clear pass/fail state, sticky summary.
   Designed for one-handed iPad use. */
.page--dev-smoke { max-width: 880px; margin: 0 auto; }
.page--dev-smoke .page-header-actions { display: flex; gap: 8px; }

.smoke-summary {
  position: sticky; top: 60px; z-index: 5;
  display: flex; gap: 14px; align-items: baseline;
  padding: 10px 14px;
  background: #fff;
  border: 1px solid var(--border, #d4d7dc);
  border-radius: 10px;
  font-size: 13px;
  margin-bottom: 16px;
  box-shadow: 0 2px 8px rgba(0,0,0,0.04);
}
.smoke-summary b { font-size: 17px; font-weight: 700; margin-right: 2px; }
.smoke-summary-pass b { color: #16a34a; }
.smoke-summary-fail b { color: #dc2626; }
.smoke-summary-todo b { color: #6b7280; }
.smoke-summary-total { color: var(--text-dim); margin-left: auto; }

.smoke-group { margin-bottom: 24px; }
.smoke-group-h {
  font-size: 15px; font-weight: 700; text-transform: uppercase;
  letter-spacing: 0.5px; color: var(--text-dim);
  margin: 0 0 8px; padding: 0 4px;
}

.smoke-item {
  display: flex; align-items: flex-start; gap: 12px;
  padding: 10px 12px;
  background: #fff;
  border: 1px solid var(--border, #d4d7dc);
  border-radius: 10px;
  margin-bottom: 8px;
  transition: background 140ms ease-out, border-color 140ms ease-out;
}
.smoke-item.is-pass { background: #f0fdf4; border-color: #86efac; }
.smoke-item.is-fail { background: #fef2f2; border-color: #fca5a5; }

.smoke-item-buttons {
  display: flex; gap: 6px; flex: 0 0 auto;
}
.smoke-btn {
  width: 44px; height: 44px;
  border: 1.5px solid var(--border, #d4d7dc);
  border-radius: 10px;
  background: #fff; color: var(--text-dim);
  font-size: 22px; font-weight: 800; line-height: 1;
  cursor: pointer; -webkit-appearance: none;
  transition: transform 100ms ease-out, background 140ms, color 140ms, border-color 140ms;
}
.smoke-btn:active { transform: scale(0.92); }
.smoke-pass:hover { background: #f0fdf4; }
.smoke-fail:hover { background: #fef2f2; }
.smoke-item.is-pass .smoke-pass { background: #16a34a; color: #fff; border-color: #16a34a; }
.smoke-item.is-fail .smoke-fail { background: #dc2626; color: #fff; border-color: #dc2626; }

.smoke-item-body { flex: 1; min-width: 0; }
.smoke-item-label {
  font-size: 15px; font-weight: 500; color: var(--text);
  line-height: 1.4;
}
.smoke-item-actions {
  display: flex; gap: 14px; margin-top: 4px;
  font-size: 12px;
}
.smoke-item-link {
  color: var(--brand-secondary, #1f5fff);
  text-decoration: none; font-weight: 600;
}
.smoke-item-link:hover { text-decoration: underline; }
.smoke-note-toggle {
  background: none; border: none; padding: 0;
  color: var(--text-dim); cursor: pointer;
  font: inherit; font-size: 12px;
}
.smoke-note-toggle:hover { color: var(--text); }
.smoke-note {
  width: 100%; margin-top: 6px;
  padding: 8px 10px;
  border: 1px solid var(--border, #d4d7dc);
  border-radius: 8px;
  font: inherit; font-size: 13px;
  resize: vertical;
}

.smoke-footnote {
  color: var(--text-dim); font-size: 12px;
  margin-top: 24px; text-align: center;
}

@media (max-width: 540px) {
  .smoke-summary { font-size: 12px; gap: 10px; }
  .smoke-summary b { font-size: 15px; }
}

/* =================================================================
   Drillboard redesign R1 — Bottom dock (light)
   2026-06-14  pivot from dark Figma chrome to a floating bottom dock
   =================================================================
   Reference: ~/Downloads/rinkboard-bottom-dock-light.html
   Pattern: centered floating tool pill + context strip, bottom-left
   mode switch (Draw / Anim / Play). The legacy left toolbar is hidden
   and the existing tool buttons stay in the DOM as forwarding targets
   so canvas.js wiring keeps working. */

body.route-drill {
  --dock-canvas:    #ffffff;
  --dock-panel:     #ffffff;
  --dock-panel-2:   #f1f2f4;
  --dock-line:      #e2e4e8;
  --dock-line-soft: #edeef1;
  --dock-text:      #1b1e25;
  --dock-text-mid:  #5c6470;
  --dock-text-faint:#9097a1;
  --dock-blue:      #0d99ff;
  --dock-shadow:    0 14px 40px rgba(17, 20, 26, 0.14);
  --dock-shadow-sm: 0 10px 30px rgba(17, 20, 26, 0.12);
}

/* ---------- Topbar: HIDDEN. Its contents (surface, time, undo/redo,
   save/print/etc.) are moved at boot into the tabs bar and the
   left rail by page_drill.js. (R6, 2026-06-14) ---------- */
body.route-drill .topbar { display: none !important; }
/* App grid-template-rows was `auto 1fr auto` — when topbar:none drops
   out of the grid, main auto-flows into the AUTO row and sizes to its
   content (only ~440px) instead of filling the viewport. Collapse the
   grid to a single 1fr row so main fills the full height under the
   nav. (Fixes the wrap being too short to center the rink.) */
body.route-drill #app { grid-template-rows: 1fr; }
body.route-drill .topbar-mode-hint {
  font-family: inherit;
  font-size: 10px;
  letter-spacing: 1px;
  color: var(--dock-text-faint);
  border: 1px solid var(--dock-line);
  border-radius: 20px;
  padding: 4px 10px;
  white-space: nowrap;
}

/* ---------- Tabs bar: now also carries action buttons on the right ---------- */
body.route-drill #drill-tabs {
  display: flex;
  align-items: center;
  gap: 6px;
  background: var(--dock-panel);
  border-bottom: 1px solid rgba(0, 0, 0, 0.08);
  padding: 4px 12px 4px 6px;
  min-height: 38px;
}
body.route-drill #drill-tabs { overflow: hidden; }
/* Tab list scrolls independently — actions stay pinned to the right.
   Without this, when the tab strip overflowed the WHOLE row scrolled
   horizontally and pushed the Share button etc. off-screen. The fade
   mask on the right edge hints there are more tabs to scroll to.
   (Ian: "how should i handle tabs and the bar when they overlap?") */
body.route-drill #drill-tab-list {
  flex: 1 1 0;
  min-width: 0;
  overflow-x: auto;
  overflow-y: hidden;
  scrollbar-width: thin;
  -webkit-mask-image: linear-gradient(to right, black calc(100% - 18px), transparent 100%);
          mask-image: linear-gradient(to right, black calc(100% - 18px), transparent 100%);
}
/* Tighter scrollbar for the tab track (WebKit). */
body.route-drill #drill-tab-list::-webkit-scrollbar { height: 4px; }
body.route-drill #drill-tab-list::-webkit-scrollbar-thumb {
  background: rgba(0, 0, 0, 0.2);
  border-radius: 2px;
}
body.route-drill #drill-tab-list::-webkit-scrollbar-track { background: transparent; }
/* Progressive collapse of right-side actions as the viewport narrows
   so the tab list always has somewhere to live. Mirrors the UX pattern
   in browser address bars: drop low-value chrome first. Ordered by
   priority — least essential collapses first. */
@media (max-width: 1200px) {
  body.route-drill #ad-slot-drillboard { display: none; }
}
@media (max-width: 1080px) {
  body.route-drill #save-status .save-status-label { display: none; }
  body.route-drill #save-status { padding: 4px 6px; }
}
@media (max-width: 980px) {
  body.route-drill #drill-tabs-slot-undo,
  body.route-drill #drill-tabs-slot-redo,
  body.route-drill #drill-tabs-actions .drill-tabs-divider { display: none; }
}
@media (max-width: 880px) {
  body.route-drill #drill-tabs-fullscreen { display: none; }
}
@media (max-width: 780px) {
  body.route-drill #drill-tabs-slot-time { display: none; }
}
body.route-drill .drill-tabs-actions {
  display: flex;
  align-items: center;
  gap: 6px;
  flex: 0 0 auto;
  margin-left: auto;
}
body.route-drill .drill-tabs-divider {
  width: 1px;
  height: 18px;
  background: var(--dock-line);
}
/* Buttons that get MOVED into the tabs actions take dock-mini styling. */
body.route-drill .drill-tabs-actions .top-icon-btn,
body.route-drill .drill-tabs-actions .rink-btn,
body.route-drill .drill-tabs-actions select.mins {
  background: var(--dock-panel);
  border: 1px solid var(--dock-line);
  color: var(--dock-text);
  border-radius: 6px;
  font-size: 11px;
  padding: 3px 8px;
  height: 28px;
  display: inline-flex;
  align-items: center;
  gap: 4px;
  cursor: pointer;
}
body.route-drill .drill-tabs-actions .top-icon-btn:hover,
body.route-drill .drill-tabs-actions .rink-btn:hover { background: var(--dock-panel-2); }
body.route-drill .drill-tabs-actions .top-icon-btn { width: 28px; padding: 0; justify-content: center; }
body.route-drill .drill-tabs-actions .top-icon-btn svg { width: 13px; height: 13px; }
body.route-drill .drill-tabs-actions select.mins { padding-right: 16px; }
/* Share button gets the brand accent — TEAM brand, never the purple
   fallback (--fg-accent was never defined, so this always rendered
   #7c5cff regardless of team colors). */
body.route-drill #drill-tabs-slot-share .top-icon-btn,
body.route-drill #drill-tabs-slot-share > * {
  background: var(--brand-primary, #7c5cff);
  border-color: var(--brand-primary, #7c5cff);
  color: #fff;
  padding: 0 10px;
  width: auto;
}
body.route-drill #drill-tabs-slot-share .top-icon-btn:hover {
  background: color-mix(in srgb, var(--brand-primary, #7c5cff) 82%, #000);
}
body.route-drill #drill-tabs-slot-share .top-icon-btn::after {
  content: 'Share';
  font-size: 11px;
  font-weight: 500;
  margin-left: 4px;
}

/* ---------- Legacy left toolbar: forced collapsed via body class
     toggle in JS init. The dock replaces it, so hide the expand-strip
     too. (Existing body.tools-collapsed CSS handles the column resize
     to 22px and toolbar display:none.) ---------- */
body.route-drill .collapse-strip.left { display: none !important; }
/* Drill-tabs strip — span columns 1 + 2 (skip the right collapse-strip
   in column 3). Starts flush at x=0 on the left, stops where the right
   sidebar's "›" chevron lives so the Drills launcher stays visible.
   (Ian: "share / full ice / time is over the drills tab — should be
   visible") */
body.route-drill main > .drill-tabs {
  grid-column: 1 / 3;
  padding-left: 0;
}

/* ---------- Canvas surround: soft gray + dot grid ---------- */
body.route-drill main {
  background: var(--dock-canvas);
}
body.route-drill .canvas-wrap {
  background: var(--dock-canvas);
  position: relative;
  /* The dock + style bar are now position:fixed (anchored to viewport,
     not the scroll container). The padding-bottom only needs to keep
     the LAST inline child (notes editor / tag input) from scrolling
     under the dock. 180px = dock area (~94px) + breathing room. */
  padding-bottom: 180px;
  /* Reserve space on the left so the rink can't slide under the
     floating DRAW/ANIM/PLAY mode rail (which lives at left:18px,
     56px wide → 74px footprint, +12px breathing room = 86px).
     (Ian: "make sure it doesn't overlap the surface") */
  padding-left: 86px;
  /* Vertically center the rink in the available space between the
     tabs bar and the floating style bar. (Ian: "can the surface be
     placed more centered vertically?") */
  justify-content: center;
}
/* When the drills sidebar is collapsed (narrow DRILLS strip on the right
   only), mirror the left rail's reservation on the right so the rink
   visually centers in the available area. With the sidebar open, the
   300px panel already balances the visual weight. (Ian: "feels weird
   when the drills tab is collapsed and the rink isn't centered") */
body.route-drill.sidebar-collapsed .canvas-wrap {
  padding-right: 86px;
}
@media (max-width: 900px) {
  body.route-drill .canvas-wrap { padding-left: 60px; }
}

/* ---------- Resizable sidebar (Ian: "make the panel wider") ----------
   The drill drawer's right column was a fixed 300px. Now it reads from
   a CSS custom property the user can change by dragging the handle on
   the sidebar's left edge. Clamped 280-640px, persisted in localStorage.
   The override only fires when the sidebar is open (not collapsed). */
body.route-drill { --sidebar-w: 300px; }
body.route-drill:not(.sidebar-collapsed):not(.tools-collapsed) .app main {
  grid-template-columns: 108px minmax(0, 1fr) var(--sidebar-w);
}
body.route-drill.tools-collapsed:not(.sidebar-collapsed) .app main {
  grid-template-columns: 22px minmax(0, 1fr) var(--sidebar-w);
}
body.route-drill aside.sidebar { position: relative; }
body.route-drill .sidebar-resize-handle {
  position: absolute;
  left: -3px;
  top: 0;
  width: 6px;
  height: 100%;
  cursor: ew-resize;
  z-index: 5;
  background: transparent;
  transition: background 120ms ease;
  touch-action: none;
}
body.route-drill .sidebar-resize-handle:hover,
body.route-drill .sidebar-resize-handle.dragging {
  background: rgba(13, 153, 255, 0.35);
}
body.route-drill .sidebar-resize-handle::before {
  content: '';
  position: absolute;
  left: 50%;
  top: 50%;
  transform: translate(-50%, -50%);
  width: 2px;
  height: 28px;
  border-radius: 2px;
  background: var(--dock-line, #e2e4e8);
}
body.route-drill .sidebar-resize-handle:hover::before,
body.route-drill .sidebar-resize-handle.dragging::before {
  background: var(--dock-blue, #0d99ff);
}
/* Draw mode: meta-fields are hidden, so the wrap doesn't need to
   reserve 180px below for them — but it DOES need ~130px so the
   rink centers in the VISIBLE area (above the floating style bar +
   dock) rather than behind them. (Ian: "more centered vertically") */
body.drill-mode-draw.route-drill .canvas-wrap { padding-bottom: calc(130px + var(--style-bar-extra, 0px)); }
/* Shrink the canvas-stage so the rink doesn't extend down under the
   floating dock + style bar. Overrides the existing min-height that
   sized for the legacy in-flow style bar (220px). The new chrome
   needs ~330px reserved below the rink. (Ian: "make the rink smaller
   so the style bar isn't over top of the rink") */
body.route-drill .canvas-stage {
  /* Reserve top/bottom slack so the rink isn't pinned to the top of
     the canvas-wrap. (Ian: "can the surface be placed more centered
     vertically?" + "make the surface a little bit bigger" ×2) */
  min-height: calc(100vh - 280px - var(--style-bar-extra, 0px)) !important;
  max-height: calc(100vh - 170px - var(--style-bar-extra, 0px));
  margin-top: auto;
  margin-bottom: auto;
  flex: 0 0 auto;
}
/* ============================================================
   R7 (final): Notes lives as a tab inside the drill drawer's sidebar.
   The meta-fields get MOVED into #panel-notes when the user clicks
   the NOTES tab. When they live inside the panel, they render as a
   normal stacked column — no floating, no fixed positioning.
   (Ian: "I want notes in the drills panel")
   ============================================================ */
/* Default in canvas-wrap (their original parent) — hidden. */
body.route-drill .canvas-wrap > .meta-fields,
body.route-drill .canvas-wrap > .meta-fields.meta-row { display: none; }
/* When relocated into the sidebar's notes panel — show as block. */
body.route-drill #panel-notes .meta-fields {
  display: block;
  position: static;
  width: auto;
  max-height: none;
  margin: 0 0 12px;
  padding: 10px 12px;
  background: var(--dock-panel-2);
  border: 1px solid var(--dock-line);
  border-radius: 10px;
  box-shadow: none;
}
/* Tags + Age live inside `.meta-fields.meta-row` — render them as TWO
   separate labelled cards in the notes panel so the user can tell at a
   glance which is which. (Ian: "can we separate tags and ages — looks
   like it's one field") */
body.route-drill #panel-notes .meta-fields.meta-row {
  display: flex;
  flex-direction: column;
  gap: 10px;
  margin: 0 0 12px;
  padding: 0;
  background: transparent;
  border: none;
  box-shadow: none;
}
body.route-drill #panel-notes .meta-fields.meta-row .tags-input {
  position: relative;
  padding: 22px 8px 8px;
  background: var(--dock-panel-2);
  border: 1px solid var(--dock-line);
  border-radius: 10px;
  min-height: 48px;
}
body.route-drill #panel-notes .meta-fields.meta-row .tags-input::before {
  position: absolute;
  top: 6px;
  left: 10px;
  font-size: 10px;
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--text-muted, #6b7280);
  pointer-events: none;
}
body.route-drill #panel-notes #tags-input::before { content: "Tags"; }
body.route-drill #panel-notes #age-input::before { content: "Age groups"; }
body.route-drill #panel-notes {
  padding: 14px 12px;
  overflow-y: auto;
}
/* Notes editor format toolbar — go icon-only when inside the sidebar
   so all the buttons fit at any sensible panel width. Hides the AI
   action labels ("Write" / "Cues" / "Adapt") and tightens spacing.
   (Ian: "the toolbar is hidden, think we need to have just icons") */
body.route-drill #panel-notes .notes-toolbar { flex-wrap: wrap; gap: 2px; padding: 4px; }
body.route-drill #panel-notes .notes-toolbar button { padding: 4px 6px; min-width: 28px; }
body.route-drill #panel-notes .notes-ai-label { display: none; }
body.route-drill #panel-notes .notes-ai-btn { padding: 4px 6px !important; }
body.route-drill #panel-notes .notes-ai-btn svg { width: 14px; height: 14px; }
/* When the notes editor is mounted inside the sidebar panel, flip the
   inline-icon picker to open DOWNWARD. The default opens UP above the
   toolbar (so it doesn't cover the text area), but in the sidebar that
   means it pops up into the DRILLS / NOTES tab header and gets clipped
   by `#panel-notes { overflow-y: auto }`. Opening downward keeps it
   inside the scroll viewport. (Ian: "the panel is hidden behind the
   drills header") */
body.route-drill #panel-notes .icon-grid {
  top: calc(100% + 4px);
  bottom: auto;
  /* Wider columns so the grid fits the narrower sidebar width without
     clipping the right edge against the panel border. */
  grid-template-columns: repeat(5, 36px);
}

/* Notes-below option — the dock toggle in the notes toolbar keeps the
   description editor UNDER the board instead of inside the drawer.
   (Ian: "show me an option where the notes are below") Desktop only;
   the ≤640px layout keeps its own arrangement. The board shrinks to
   make room (same viewport math as .canvas-stage above, minus the
   strip) and the strip ends above the floating dock reserve. */
@media (min-width: 641px) {
  /* Draw mode only — the Motion timeline owns the bottom strip.
     Tags + age groups AND the notes editor all dock below the board
     (Ian: "tags, age groups and notes below the rink"). The board
     keeps its normal height — the column scrolls down to the fields
     ("keep the surface the same height as it was before, we can
     scroll down"). */
  body.route-drill.drill-notes-below.drill-mode-draw .canvas-wrap > .meta-fields {
    display: flex;
    width: min(940px, calc(100% - 24px));
    margin: 8px auto 0;
  }
  body.route-drill.drill-notes-below.drill-mode-draw .canvas-wrap > .meta-fields.meta-row {
    flex-direction: row;
    gap: 10px;
  }
  /* Start the docked cluster a full screen below the rink so nothing
     pokes out from behind the floating style bar / dock at rest —
     the clearance lives on the leading OFFER slot (first in the flow,
     and it still provides the gap when no offer is configured). */
  body.route-drill.drill-notes-below.drill-mode-draw .canvas-wrap > [data-offer-card] {
    margin-top: max(160px, calc(100vh - 700px));
  }
  /* Clear the floating style bar + dock so the last field scrolls
     fully above the chrome. */
  body.route-drill.drill-notes-below.drill-mode-draw .canvas-wrap {
    padding-bottom: calc(250px + var(--style-bar-extra, 0px));
    /* The wrap's justify-content:center ALSO clips overflowing content
       above the scrollable area — flow from the top in below mode. */
    justify-content: flex-start;
  }
  /* The stage's margin:auto centering CLIPS the top of the rink once the
     wrap overflows (flexbox centering + overflow pushes content above the
     scrollable area — Ian: "the surface is half visible"). In below mode
     the column flows from the top instead. */
  body.route-drill.drill-notes-below.drill-mode-draw .canvas-stage {
    margin-top: 12px;
    margin-bottom: 0;
  }
  body.route-drill.drill-notes-below .canvas-wrap > .meta-fields:not(.meta-row) .notes-editor { width: 100%; }
  /* No height cap on the description (Ian: "on desktop we don't need
     to limit the description") — long notes grow naturally and the
     board column scrolls. */
  body.route-drill.drill-notes-below .canvas-wrap > .meta-fields:not(.meta-row) .notes-area {
    min-height: 64px;
  }
  body.route-drill.drill-notes-below .canvas-wrap { overflow-y: auto; }
}
/* The dock toggle rides at the right end of the notes toolbar. */
body.route-drill .notes-dock-btn {
  margin-left: auto;
  display: inline-flex;
  align-items: center;
  gap: 4px;
}
body.route-drill .notes-dock-btn .notes-dock-label { font-size: 11px; font-weight: 600; white-space: nowrap; }
@media (max-width: 640px) { body.route-drill .notes-dock-btn { display: none; } }

/* ============================================================
   R4: Animate mode — Photoshop-style timeline.
   Full-width strip pinned to the viewport bottom, like the Photoshop
   animation panel. The drawing dock + style bar float ABOVE it so the
   user can edit while scrubbing frames. (Ian: "treat it like the
   timeline panel in photoshop")
   ============================================================ */
body.drill-mode-animate .anim-panel { display: flex !important; }
body.drill-mode-animate.route-drill .anim-panel {
  position: fixed;
  left: 0;
  right: 0;
  bottom: 0;
  transform: none;
  width: 100vw;
  max-width: 100vw;
  z-index: 36;
  background: var(--dock-panel);
  border: none;
  border-top: 1px solid rgba(0, 0, 0, 0.10);
  border-radius: 0;
  box-shadow: 0 -10px 30px rgba(17, 20, 26, 0.10);
  padding: 10px 16px;
  flex-wrap: wrap;
  gap: 8px;
  align-items: center;
}
/* Lift the drawing dock + style bar ABOVE the motion panel. Driven by the
   panel's REAL height (--anim-panel-h, published by animation.js) so they
   never overlap when the panel grows (guided hint / scrubber / toolbar wrap).
   The +74 keeps the style bar the same distance above the dock as before
   (dock height ~54 + ~12 gap + 8 base). Fallback = the old fixed values. */
body.drill-mode-animate.route-drill .drill-dock   { bottom: calc(var(--anim-panel-h, 160px) + 8px); }
body.drill-mode-animate.route-drill .line-picker  { bottom: calc(var(--anim-panel-h, 160px) + 74px + var(--dock-ctx-lift, 0px)); }
/* Stop the mode switch from sitting in front of the strip on short
   viewports — move it up so it clears the timeline. */
body.drill-mode-animate.route-drill .drill-mode-switch { top: calc(50% - 70px); }
/* Shrink the rink in animate mode so it doesn't slip behind the
   tools or the bottom timeline. */
/* Reserve the bottom chrome (anim panel + dock + style bar) so the rink sits
   ABOVE the fixed style bar. The reservation lives on the WRAP's padding-bottom
   (NOT a stage margin — a stage margin stacked on top of this padding and
   double-reserved, squashing the rink to a sliver with a big dead gap). The
   stage then simply FILLS the wrap's content area, so the rink is as large as
   possible while still clearing the chrome. Reserve = the reliable
   --anim-panel-h (panel height) + 150px (dock + style bar above it). The
   min(…, 55vh) CAP guarantees the wrap can never reserve away the whole stage —
   even if the panel height spikes, the rink keeps ≥45vh and never vanishes.
   The stage ResizeObserver re-runs fitCanvas (fit-to-contain) as the height
   changes. (2026-07-04 "rink disappears" fix — replaced the fragile measured
   --anim-chrome-h margin that over-reserved to zero.) */
body.drill-mode-animate.route-drill .canvas-wrap {
  padding-bottom: min(calc(var(--anim-panel-h, 160px) + 150px), 55vh) !important;
}
body.drill-mode-animate.route-drill .canvas-stage {
  margin: 0 !important;
  min-height: 0 !important;
  max-height: none !important;
  flex: 1 1 auto !important;
}
/* Bottom Photoshop timeline overlays the bottom edge of the viewport.
   The drills + notes sidebar panels are scroll containers — pad their
   bottom so card lists / textareas scroll above the timeline strip
   instead of running beneath it.
   NOTE: do NOT use `bottom:` on `aside.sidebar` — it's position:relative
   inside the grid, so `bottom` shifts it upward (top: -140px layout
   bug). Pad the inner scroll panels instead. */
body.drill-mode-animate.route-drill #panel-drills,
body.drill-mode-animate.route-drill #panel-notes {
  padding-bottom: 140px;
}

/* ============================================================
   R5: Drill drawer launcher — make the right `›` chevron a clear
   "Drills" pill so users see they can open the drawer. (2026-06-14)
   ============================================================ */
body.route-drill.sidebar-collapsed .collapse-strip.right {
  background: var(--dock-panel);
  border: 1px solid rgba(0, 0, 0, 0.09);
  border-radius: 8px 0 0 8px;
  box-shadow: var(--dock-shadow-sm);
  color: var(--dock-text-mid);
  font-size: 10px;
  font-family: inherit;
  letter-spacing: 0.6px;
  width: 28px;
  display: flex !important;
  align-items: center;
  justify-content: center;
  writing-mode: vertical-rl;
  text-orientation: mixed;
  padding: 12px 4px;
  cursor: pointer;
  z-index: 36;
  /* Content is replaced via JS to show "DRILLS ›" instead of just "‹" */
}
body.route-drill.sidebar-collapsed .collapse-strip.right:hover {
  background: var(--dock-panel-2);
  color: var(--dock-text);
}

/* ============================================================
   R3: Context strip morph — hide irrelevant groups in the style bar
   based on the active tool. (2026-06-14)
   ============================================================ */
/* Eraser: only the size slider matters. */
body.route-drill:has(.tool[data-tool="eraser"].active) .line-picker .line-picker-group:not(.lpg-size),
body.route-drill:has(.tool[data-tool="eraser"].active) .line-picker .line-picker-divider {
  display: none;
}
/* Text + every stamp-style tool (puck / cone / circle / rect / triangle
   / players / goalie stances): style/ending don't apply; show only
   color + size. */
body.route-drill:has(.tool[data-tool="text"].active) .line-picker .lpg-style,
body.route-drill:has(.tool[data-tool="text"].active) .line-picker .lpg-ending,
body.route-drill:has(.tool[data-tool="text"].active) .line-picker .lpd-style,
body.route-drill:has(.tool[data-tool="text"].active) .line-picker .line-picker-divider:first-of-type,
body.route-drill:has(.tool[data-tool="puck"].active) .line-picker .lpg-style,
body.route-drill:has(.tool[data-tool="puck"].active) .line-picker .lpg-ending,
body.route-drill:has(.tool[data-tool="puck"].active) .line-picker .lpd-style,
body.route-drill:has(.tool[data-tool="cone"].active) .line-picker .lpg-style,
body.route-drill:has(.tool[data-tool="cone"].active) .line-picker .lpg-ending,
body.route-drill:has(.tool[data-tool="cone"].active) .line-picker .lpd-style,
body.route-drill:has(.tool[data-tool="circle"].active) .line-picker .lpg-style,
body.route-drill:has(.tool[data-tool="circle"].active) .line-picker .lpg-ending,
body.route-drill:has(.tool[data-tool="circle"].active) .line-picker .lpd-style,
body.route-drill:has(.tool[data-tool="rect"].active) .line-picker .lpg-style,
body.route-drill:has(.tool[data-tool="rect"].active) .line-picker .lpg-ending,
body.route-drill:has(.tool[data-tool="rect"].active) .line-picker .lpd-style,
body.route-drill:has(.tool[data-tool="triangle"].active) .line-picker .lpg-style,
body.route-drill:has(.tool[data-tool="triangle"].active) .line-picker .lpg-ending,
body.route-drill:has(.tool[data-tool="triangle"].active) .line-picker .lpd-style,
body.route-drill:has(.tool[data-tool="x"].active) .line-picker .lpg-style,
body.route-drill:has(.tool[data-tool="x"].active) .line-picker .lpg-ending,
body.route-drill:has(.tool[data-tool="x"].active) .line-picker .lpd-style,
body.route-drill:has(.tool[data-tool^="g-"].active) .line-picker .lpg-style,
body.route-drill:has(.tool[data-tool^="g-"].active) .line-picker .lpg-ending,
body.route-drill:has(.tool[data-tool^="g-"].active) .line-picker .lpd-style,
body.route-drill:has(.tool[data-tool^="label-"].active) .line-picker .lpg-style,
body.route-drill:has(.tool[data-tool^="label-"].active) .line-picker .lpg-ending,
body.route-drill:has(.tool[data-tool^="label-"].active) .line-picker .lpd-style { display: none; }
/* Hide the style bar when the Move tool is active AND nothing is selected
   — there's nothing to style. But the moment a shape IS selected, bring the
   bar back so the coach can recolor / resize / restyle it (clicking a swatch
   recolours the selection; the style-bar handlers already target
   state.selectedShape). */
body.route-drill:has(.tool[data-tool="select"].active):not(.shape-selected) .line-picker {
  display: none;
}
/* With a shape selected, un-hide the style + ending groups (the
   tool-kind="none" rules set them visibility:hidden) so a selected line can
   have its style/ending changed too. Color + size are already shown. */
body.route-drill.shape-selected .lpg-style,
body.route-drill.shape-selected .lpg-ending,
body.route-drill.shape-selected .lpd-style,
body.route-drill.shape-selected .lpd-color {
  visibility: visible;
}

/* ---------- Mode switch: LEFT EDGE, vertically centered ----------
   position:fixed so it stays glued to the viewport even when the
   canvas-wrap scrolls. (Inside canvas-wrap it scrolled with the
   description editor / tag input below the rink, which was the
   "interfering with the floating nav" issue.) */
body.route-drill .drill-mode-switch {
  position: fixed;
  left: 18px;
  top: 50%;
  bottom: auto;
  transform: translateY(-50%);
  z-index: 30;
  display: flex;
  flex-direction: column;
  gap: 4px;
  background: var(--dock-panel);
  border: 1px solid rgba(0, 0, 0, 0.09);
  border-radius: 12px;
  padding: 5px;
  box-shadow: var(--dock-shadow-sm);
}
body.route-drill .drill-mode-switch .rail-section--mode {
  display: flex;
  flex-direction: column;
  gap: 2px;
  width: 100%;
}
body.route-drill .drill-mode-switch .rail-section--mode button {
  width: 100%;
  height: 44px;
  border: none;
  background: transparent;
  border-radius: 9px;
  color: var(--dock-text-faint);
  cursor: pointer;
  display: grid;
  place-items: center;
  gap: 2px;
  transition: background 140ms ease, color 140ms ease;
}
/* Fallback (in case some legacy code-path renders mode buttons OUTSIDE
   the rail-section--mode wrapper). */
body.route-drill .drill-mode-switch > button {
  width: 100%;
  height: 44px;
  border: none;
  background: transparent;
  border-radius: 9px;
  color: var(--dock-text-faint);
  cursor: pointer;
  display: grid;
  place-items: center;
  gap: 2px;
  transition: background 140ms ease, color 140ms ease;
}
body.route-drill .drill-mode-switch button:hover {
  background: var(--dock-panel-2);
  color: var(--dock-text-mid);
}
body.route-drill .drill-mode-switch button.on {
  background: var(--dock-panel-2);
  color: var(--dock-text);
}
body.route-drill .drill-mode-switch button.on svg {
  color: var(--dock-blue);
}
body.route-drill .drill-mode-switch button svg {
  width: 19px;
  height: 19px;
}
body.route-drill .drill-mode-switch .ml {
  font-size: 8px;
  font-family: inherit;
  letter-spacing: 0.5px;
  margin-top: 1px;
}
/* Expanded rail layout: stacked sections with thin dividers + tiny
   uppercase labels. The DRAW/ANIM/PLAY trio stays on top; FILE and
   EXPORT sections are populated at boot by moving icon buttons over
   from the (hidden) legacy topbar. (R6, 2026-06-14) */
body.route-drill .drill-mode-switch .rail-divider {
  width: 36px;
  height: 1px;
  background: var(--dock-line);
  margin: 4px auto;
}
body.route-drill .drill-mode-switch .rail-label {
  font-size: 8px;
  font-family: inherit;
  letter-spacing: 0.6px;
  color: var(--dock-text-faint);
  text-align: center;
  padding: 0 0 4px;
}
body.route-drill .drill-mode-switch .rail-section--actions {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 4px;
}
body.route-drill .drill-mode-switch .rail-section--actions .top-icon-btn {
  width: 28px;
  height: 28px;
  border: 1px solid var(--dock-line);
  background: transparent;
  color: var(--dock-text-mid);
  border-radius: 6px;
  cursor: pointer;
  display: grid;
  place-items: center;
  padding: 0;
}
body.route-drill .drill-mode-switch .rail-section--actions .top-icon-btn:hover {
  background: var(--dock-panel-2);
  color: var(--dock-text);
}
body.route-drill .drill-mode-switch .rail-section--actions .top-icon-btn svg { width: 13px; height: 13px; }

/* ---------- Bottom dock — centered floating column ----------
   position:fixed so it doesn't scroll with the description editor /
   tag input below the rink. The dock is centered to the viewport
   minus the collapsed sidebar's 22px column on the right — close
   enough to center on the canvas without absolute positioning. */
body.route-drill .drill-dock {
  position: fixed;
  left: 50%;
  bottom: 20px;
  transform: translateX(-50%);
  /* Above the style bar (z=35) so the per-tool tooltips that float
     UP from each .dock-tool can render OVER the bar instead of being
     hidden behind it. (Ian: "tooltips are under the style bar") */
  z-index: 40;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 9px;
  width: max-content;
  /* Never wider than the viewport — the pills below scroll horizontally
     instead of wrapping onto a second row when the screen is narrow. */
  max-width: calc(100vw - 24px);
}
/* Respect the [hidden] attribute on the ctx strip — without this rule
   the display:flex below would override hidden's display:none and leave
   an empty 42px-tall white box stacked above the primary pill, which
   pushed the line-picker down INTO the dock area. (2026-06-14) */
body.route-drill .drill-dock-ctx[hidden] { display: none; }
body.route-drill .drill-dock-ctx {
  display: flex;
  align-items: center;
  gap: 8px;
  background: var(--dock-panel);
  border: 1px solid rgba(0, 0, 0, 0.09);
  border-radius: 11px;
  padding: 6px 8px;
  box-shadow: var(--dock-shadow-sm);
  min-height: 42px;
  /* Scroll sideways rather than wrapping when narrow. */
  flex-wrap: nowrap;
  max-width: 100%;
  overflow-x: auto;
  overscroll-behavior-x: contain;
  -webkit-overflow-scrolling: touch;
  touch-action: pan-x;
  scrollbar-width: none;
}
body.route-drill .drill-dock-ctx::-webkit-scrollbar { display: none; }
body.route-drill .drill-dock-ctx > * { flex-shrink: 0; }
body.route-drill .drill-dock-primary {
  display: flex;
  align-items: center;
  gap: 2px;
  background: var(--dock-panel);
  border: 1px solid rgba(0, 0, 0, 0.09);
  border-radius: 14px;
  padding: 7px;
  box-shadow: var(--dock-shadow);
  /* Single row that scrolls sideways when the screen can't fit every tool —
     never wraps onto a second line (desktop-small, iPad, or phone). The
     tooltip is a fixed bubble on <body> (tooltip.js) so overflow here can't
     clip it. */
  flex-wrap: nowrap;
  max-width: 100%;
  overflow-x: auto;
  overscroll-behavior-x: contain;
  -webkit-overflow-scrolling: touch;
  touch-action: pan-x;
  scrollbar-width: none;
}
body.route-drill .drill-dock-primary::-webkit-scrollbar { display: none; }
body.route-drill .dock-tool {
  position: relative;
  width: 40px;
  height: 40px;
  flex-shrink: 0;
  border: none;
  padding: 0;   /* UA default 1px 6px let the 34px pencil img overflow its content box → sat 3px right of centre (Ian 2026-07-13) */
  background: transparent;
  border-radius: 10px;
  color: var(--dock-text-mid);
  cursor: pointer;
  display: grid;
  place-items: center;
  transition: background 140ms ease, color 140ms ease, transform 120ms ease;
}
body.route-drill .dock-tool svg { width: 21px; height: 21px; }
/* PNG icons (e.g. Ian's pencil.png on the pen tool) — size to fit the
   dock chip and lock the aspect ratio. Sized larger than the SVGs so the
   pencil dominates its chip the way Figma's pencil does in their
   reference toolbar. (Ian: "i want the pencil to be bigger ... it should
   feel like this") */
body.route-drill .dock-tool img {
  width: 34px;
  height: 34px;
  object-fit: contain;
  pointer-events: none;
  user-select: none;
  -webkit-user-drag: none;
}
/* Same sizing for the hidden source `.tool` buttons that mirrorIcons()
   clones from — so the legacy toolbar (and any tooltip preview) shows
   the same pencil at the same size. */
body.route-drill .toolbar .tool img,
body.route-drill .drill-dock-all .dock-tool img { width: 34px; height: 34px; object-fit: contain; }
/* Figma flourish: when the Pencil tool is active, the cursor over the
   drawing surface IS a pencil. Scoped to `#drawing` (the actual drawing
   canvas) so the pencil only appears over the rink — the previous scope
   (`.canvas-stage`) bled the pencil onto the empty padding around the
   rink, which the user saw as "a weird pencil icon... outside the rink".
   Hotspot is the tip (3, 29 — bottom-left). Falls back to crosshair on
   older browsers. (Ian: "there is a weird pencil icon as the cursor on
   the page... its outside the rink") */
body.route-drill:has(.tool[data-tool="pen"].active) #drawing {
  cursor: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='32' height='32' viewBox='0 0 32 32'><g transform='rotate(-45 16 16)'><rect x='14' y='4' width='4' height='3' fill='%23111'/><rect x='14' y='7' width='4' height='14' fill='%23f4f1ea' stroke='%23222' stroke-width='0.5'/><rect x='14' y='21' width='4' height='2' fill='%23222'/><polygon points='14,23 18,23 16,29' fill='%23111'/></g></svg>") 3 29, crosshair;
}
body.route-drill .dock-tool:hover {
  background: var(--dock-panel-2);
  color: var(--dock-text);
  transform: translateY(-1px);
}
body.route-drill .dock-tool.active {
  background: var(--dock-blue);
  color: #fff;
}
/* Letter-glyph dock tools (X, O) — bold mono-ish letter centered in
   the chip; matches the existing position-label vibe. */
body.route-drill .dock-tool--letter span {
  font-family: inherit;
  font-weight: 600;
  font-size: 16px;
  letter-spacing: 0.5px;
  line-height: 1;
}
body.route-drill .dock-divider {
  width: 1px;
  height: 26px;
  background: var(--dock-line);
  margin: 0 5px;
}
/* Tooltip for .dock-tool — handled by tooltip.js (pc-tooltip). The
   previous CSS `::after` here duplicated that bubble, so a hover showed
   two pills (one above, one on the side). The JS bubble lives in <body>
   and handles viewport edges + delay properly. (Ian: "i have two
   tooltips showing. one above and one on the side") */
/* Down-caret indicator on dock buttons that open a flyout. */
body.route-drill .dock-tool[data-flyout]::before {
  content: '';
  position: absolute;
  right: 4px;
  bottom: 4px;
  width: 0;
  height: 0;
  border-left: 4px solid transparent;
  border-bottom: 4px solid currentColor;
  opacity: 0.5;
}

/* ---------- Flyout panels above the dock ---------- */
body.route-drill .dock-flyout {
  position: absolute;
  bottom: 72px;
  z-index: 40;
  background: var(--dock-panel);
  border: 1px solid rgba(0, 0, 0, 0.09);
  border-radius: 12px;
  padding: 10px;
  box-shadow: 0 16px 44px rgba(17, 20, 26, 0.14);
  display: none;
  min-width: 180px;
}
body.route-drill .dock-flyout.open { display: block; animation: dock-rise 180ms ease both; }
@keyframes dock-rise {
  from { opacity: 0; transform: translateY(8px); }
  to   { opacity: 1; transform: translateY(0); }
}
body.route-drill .dock-flyout-row {
  display: flex;
  flex-wrap: wrap;
  gap: 5px;
}
body.route-drill .dock-flyout-item {
  width: 40px;
  height: 40px;
  border: none;
  background: var(--dock-panel-2);
  border-radius: 9px;
  color: var(--dock-text-mid);
  cursor: pointer;
  display: grid;
  place-items: center;
  transition: background 130ms ease, color 130ms ease, transform 120ms ease;
  padding: 0;
}
body.route-drill .dock-flyout-item:hover {
  background: var(--dock-line-soft);
  color: var(--dock-text);
  transform: translateY(-1px);
}
body.route-drill .dock-flyout-item svg { width: 20px; height: 20px; }
/* Position-label stamps (LW, C, RW, LD, RD, G, F, D — small SVG circles
   with text labels inside) come through as <img> elements with embedded
   text. The default 20px sizing renders the text too small to read.
   Bump the img size so the letters are legible. (Ian: "the stamps that
   have numbers on them ... in the bar, they are very small. can we make
   them bigger?") */
body.route-drill .dock-flyout-item img { width: 30px; height: 30px; object-fit: contain; }
body.route-drill .drill-dock-all .dock-tool img { width: 30px; height: 30px; object-fit: contain; }

/* Expanded all-tools strip — sits ABOVE the dock primary pill when
   #dock-expand-toggle is on. Shows every shape, player, stamp, and
   goalie tool inline so the user doesn't have to open four flyouts.
   (2026-06-14 "show all options on the toolbar") */
body.route-drill .drill-dock-all {
  display: none;
  align-items: center;
  gap: 4px;
  background: var(--dock-panel);
  border: 1px solid rgba(0, 0, 0, 0.09);
  border-radius: 14px;
  padding: 6px 8px;
  box-shadow: var(--dock-shadow-sm);
  /* One row, always: when the strip is wider than the screen it scrolls
     sideways instead of wrapping onto a second line. (Ian: "scroll left to
     right at its max width rather than have objects wrap to a new line") */
  flex-wrap: nowrap;
  overflow-x: auto;
  overflow-y: hidden;
  max-width: calc(100vw - 80px);
  -webkit-overflow-scrolling: touch;
  overscroll-behavior-x: contain;
  scrollbar-width: thin;
  scrollbar-color: rgba(0, 0, 0, 0.25) transparent;
}
body.route-drill .drill-dock-all::-webkit-scrollbar { height: 5px; }
body.route-drill .drill-dock-all::-webkit-scrollbar-thumb { background: rgba(0, 0, 0, 0.22); border-radius: 3px; }
body.route-drill .drill-dock-all::-webkit-scrollbar-track { background: transparent; }
body.route-drill .drill-dock-all > * { flex-shrink: 0; }
body.drill-dock-all-tools .drill-dock-all { display: flex; }
/* When the expanded strip is on, hide the compact primary pill so
   there's only one toolbar on screen at a time. The expand toggle
   moves into the expanded strip so the user can still collapse back. */
body.drill-dock-all-tools .drill-dock-primary { display: none; }
body.route-drill .drill-dock-all .dock-tool {
  width: 36px;
  height: 36px;
}
body.route-drill .drill-dock-all .dock-tool svg { width: 18px; height: 18px; }
body.route-drill .drill-dock-all .dock-group-label {
  font-family: inherit;
  font-size: 9px;
  letter-spacing: 0.6px;
  color: var(--dock-text-faint);
  text-transform: uppercase;
  padding: 0 6px;
}
body.route-drill .drill-dock-all .dock-divider {
  width: 1px;
  height: 18px;
  background: var(--dock-line);
  margin: 0 2px;
}

/* Toggle button — light up blue when "show all" is active. */
body.drill-dock-all-tools .dock-expand-toggle {
  background: var(--dock-blue);
  color: #fff;
}
body.drill-dock-all-tools .dock-expand-toggle .icon-expand { display: none; }
body.drill-dock-all-tools .dock-expand-toggle .icon-collapse { display: block; }

/* ---------- Floating style bar above the dock ----------
   The legacy .line-picker (color swatches + line styles + endings +
   pos-num picker) gets repositioned as a floating panel just above
   the dock primary pill. Same JS hooks, brand-new chrome.
   position:fixed so it stays glued to the viewport like the dock. */
body.route-drill .line-picker {
  position: fixed;
  left: 50%;
  bottom: calc(86px + var(--dock-ctx-lift, 0px));            /* 20 (dock bottom) + 54 (pill h) + 12 gap */
  /* Explicit width basis. As a fixed element with left:50% and no width,
     shrink-to-fit capped the bar at 50vw (590px on a 1180px iPad) — so with
     wrapping enabled at ≤1366px the size group dropped to a 2nd row even
     with 1100px free. max-content lets it use the room; max-width still caps. */
  width: max-content;
  transform: translateX(-50%);
  z-index: 35;
  margin-top: 0;
  background: var(--dock-panel);
  border: 1px solid rgba(0, 0, 0, 0.09);
  border-radius: 11px;
  box-shadow: var(--dock-shadow-sm);
  padding: 5px 8px;
  max-width: calc(100vw - 80px);
  gap: 6px;
}
/* Tighten the floating style bar — drop the STYLE/ENDING/SIZE labels
   and shrink the inter-group gap so the bar isn't twice as wide as
   the dock pill. The buttons themselves are unambiguous enough.
   Also shrinks the line-style previews + swatches + slider so the
   bar matches the dock pill's width. */
body.route-drill .line-picker .lp-label { display: none; }
body.route-drill .line-picker .line-picker-group { gap: 2px; padding: 0; }
body.route-drill .line-picker .line-picker-divider {
  width: 1px;
  height: 16px;
  background: var(--dock-line);
  margin: 0 3px;
}
body.route-drill .line-picker .lp-btn { padding: 2px 3px; border-radius: 5px; }
body.route-drill .line-picker .lp-btn svg,
body.route-drill .line-picker .lp-btn img { width: 28px; height: 12px; }
body.route-drill .line-picker .lp-swatches { gap: 3px; }
body.route-drill .line-picker .lp-swatches .swatch { width: 18px; height: 18px; }
body.route-drill .line-picker input[type="range"] { max-width: 80px; }

/* Rink-menu flipped-surface thumbnails — same art rotated 180°. */
#rink-menu .rink-thumb--mirrored { transform: rotate(180deg); }
/* Rink-menu mirror toggle (retired 2026-09-04 — flipped variants are
   now their own menu items; kept for any cached markup). */
#rink-menu .rink-mirror-row {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 8px 10px;
  margin-top: 4px;
  border-top: 1px solid rgba(0, 0, 0, 0.08);
  cursor: pointer;
  font-size: 13px;
  color: var(--text, #16181d);
  user-select: none;
}
#rink-menu .rink-mirror-row:hover { background: rgba(0, 0, 0, 0.04); }
#rink-menu .rink-mirror-row .rmr-state {
  margin-left: auto;
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.4px;
  padding: 2px 8px;
  border-radius: 999px;
  background: rgba(0, 0, 0, 0.07);
  color: var(--text-mid, #4b5058);
}
#rink-menu .rink-mirror-row.on .rmr-state { background: var(--brand-primary); color: #fff; }

/* ---------- Goalie mode: dock pill swaps to goalie tools ----------
   When body.dock-goalie-mode is on, the regular dock-primary buttons
   hide and the goalie-mode strip takes over. Tapping the back button
   restores the normal pill. */
body.route-drill .dock-goalie-strip {
  display: none;
  align-items: center;
  flex-wrap: wrap;
  justify-content: center;
  gap: 4px;
  background: var(--dock-panel);
  border: 1px solid rgba(0, 0, 0, 0.09);
  border-radius: 14px;
  padding: 7px;
  box-shadow: var(--dock-shadow);
}
body.dock-goalie-mode.route-drill .drill-dock-primary { display: none; }
body.dock-goalie-mode.route-drill .dock-goalie-strip  { display: flex; }
body.route-drill .dock-goalie-strip .dock-tool { width: 40px; height: 40px; }
body.route-drill .dock-goalie-back {
  width: 32px;
  height: 40px;
  border: none;
  background: transparent;
  border-radius: 8px;
  color: var(--dock-text-mid);
  cursor: pointer;
  display: grid;
  place-items: center;
  margin-right: 2px;
}
body.route-drill .dock-goalie-back:hover { background: var(--dock-panel-2); color: var(--dock-text); }
body.route-drill .dock-goalie-label {
  font-family: inherit;
  font-size: 10px;
  letter-spacing: 0.6px;
  color: var(--dock-text-faint);
  text-transform: uppercase;
  padding-right: 6px;
}

/* ---------- Mode-specific visibility ---------- */
/* Keep the dock primary pill visible in animate mode so the user can
   draw + edit while scrubbing frames. (Ian: "I need to be able to
   edit drills when I'm animating and going frame by frame") */
body.drill-mode-present .drill-dock-primary { display: none; }
body.drill-mode-present .drill-dock-ctx { display: none; }
/* Hide the inline animation panel + frame thumb strip when in DRAW
   mode — they conflict with the floating dock at the viewport bottom
   and the user reaches them via the bottom-left mode switch → ANIM.
   R4 will move them into the dock area when ANIM mode is active. */
body.drill-mode-draw .anim-panel { display: none; }
body.drill-mode-present .canvas-wrap::before {
  content: '';
  position: absolute;
  inset: 0;
  background: rgba(0, 0, 0, 0.32);
  z-index: 5;
  pointer-events: none;
}

/* ---------- iPad / narrow viewport ---------- */
@media (max-width: 900px) {
  body.route-drill .canvas-wrap { padding-bottom: 180px; }
  body.route-drill .drill-mode-switch { left: 12px; }
  body.route-drill .drill-mode-switch button { width: 38px; height: 38px; }
  body.route-drill .drill-mode-switch button svg { width: 16px; height: 16px; }
  body.route-drill .drill-dock { bottom: 14px; }
  body.route-drill .dock-tool { width: 38px; height: 38px; }
  body.route-drill .dock-tool svg { width: 19px; height: 19px; }
}

/* ---------- Mobile sweep — phones (≤640px) ----------
   (Ian: "make this look good for mobile") */
@media (max-width: 640px) {
  /* Tab strip: compact tabs, hide divider text, smaller surface/time pills */
  body.route-drill #drill-tabs { padding: 4px 8px 4px 4px; min-height: 36px; gap: 4px; }
  body.route-drill .drill-tab { padding: 3px 8px; font-size: 10px; max-width: 100px; }
  body.route-drill .drill-tabs-actions { gap: 4px; }
  body.route-drill .drill-tabs-actions .top-icon-btn,
  body.route-drill .drill-tabs-actions .rink-btn,
  body.route-drill .drill-tabs-actions select.mins { height: 26px; font-size: 10px; padding: 2px 6px; }
  body.route-drill #drill-tabs-slot-share .top-icon-btn::after { content: none; }
  body.route-drill #drill-tabs-slot-share .top-icon-btn { width: 26px; padding: 0; }
  body.route-drill .drill-tabs-divider { display: none; }

  /* Mode switch: even smaller, hugs the edge */
  body.route-drill .drill-mode-switch { left: 6px; padding: 3px; gap: 2px; }
  body.route-drill .drill-mode-switch button { width: 34px; height: 34px; }
  body.route-drill .drill-mode-switch button svg { width: 14px; height: 14px; }
  body.route-drill .drill-mode-switch .ml { font-size: 7px; }
  body.route-drill .drill-mode-switch .rail-label { font-size: 7px; padding: 0 0 2px; }
  body.route-drill .drill-mode-switch .rail-section--actions { gap: 3px; }
  body.route-drill .drill-mode-switch .rail-section--actions .top-icon-btn { width: 24px; height: 24px; }
  body.route-drill .drill-mode-switch .rail-section--actions .top-icon-btn svg { width: 11px; height: 11px; }

  /* Canvas: tighter padding so the rink can use what's left */
  body.route-drill .canvas-wrap { padding-left: 48px; padding-bottom: 130px; }

  /* Floating dock: shrink chips, allow horizontal scroll for the
     expanded "show all" strip so even a 360px phone can tap any tool. */
  body.route-drill .drill-dock { bottom: 12px; max-width: calc(100vw - 16px); }
  body.route-drill .drill-dock-primary { padding: 4px; gap: 1px; flex-wrap: nowrap; justify-content: flex-start; }
  body.route-drill .dock-tool { width: 34px; height: 34px; border-radius: 8px; }
  body.route-drill .dock-tool svg { width: 16px; height: 16px; }
  body.route-drill .dock-tool--letter span { font-size: 13px; }
  body.route-drill .drill-dock-all { padding: 4px 6px; overflow-x: auto; flex-wrap: nowrap; max-width: calc(100vw - 16px); }
  body.route-drill .drill-dock-all .dock-tool { width: 30px; height: 30px; flex-shrink: 0; }
  body.route-drill .drill-dock-all .dock-tool svg { width: 14px; height: 14px; }
  body.route-drill .drill-dock-all .dock-group-label { font-size: 8px; padding: 0 4px; flex-shrink: 0; }

  /* Style bar: smaller buttons + tighter padding, can wrap */
  body.route-drill .line-picker { bottom: calc(70px + var(--dock-ctx-lift, 0px)); padding: 3px 6px; flex-wrap: wrap; max-width: calc(100vw - 16px); }
  body.route-drill .line-picker .lp-btn { padding: 1px 3px; }
  body.route-drill .line-picker .lp-btn svg,
  body.route-drill .line-picker .lp-btn img { width: 24px; height: 11px; }
  body.route-drill .line-picker .lp-swatches .swatch { width: 16px; height: 16px; }
  body.route-drill .line-picker input[type="range"] { max-width: 60px; }
  body.drill-mode-animate.route-drill .line-picker { bottom: calc(110px + var(--dock-ctx-lift, 0px)); }

  /* Animation panel: smaller text + buttons in animate mode */
  body.drill-mode-animate.route-drill .anim-panel { bottom: 140px; padding: 6px 8px; font-size: 10px; gap: 4px; }

  /* Sidebar: full-width slide-over on top of everything when open;
     keep the 22px collapsed strip so the user can re-open it. */
  body.route-drill:not(.sidebar-collapsed) .app main {
    grid-template-columns: 22px minmax(0, 1fr) 22px;
  }
  body.route-drill:not(.sidebar-collapsed) aside.sidebar {
    position: fixed;
    top: 90px;
    right: 0;
    bottom: 0;
    width: min(100vw, 360px);
    z-index: 38;
    box-shadow: -10px 0 30px rgba(0,0,0,0.25);
  }
  body.route-drill .sidebar-resize-handle { display: none; } /* Drag handle isn't useful on phones */
  body.route-drill .collapse-strip.right { font-size: 9px; padding: 8px 3px; }

  /* DRILLS / NOTES sidebar tabs */
  body.route-drill .sidebar-tab { padding: 6px 8px; font-size: 11px; }

  /* Notes panel: full-width chrome, even tighter buttons */
  body.route-drill #panel-notes { padding: 10px 8px; }
  body.route-drill #panel-notes .notes-toolbar button { padding: 3px 5px; min-width: 24px; }
}

/* ---------- Tablets / small laptops 641-900px ---------- */
@media (max-width: 900px) and (min-width: 641px) {
  body.route-drill .drill-tabs-divider { display: none; }
}

/* ============================================================
   Save status pill (Option B, 2026-06-15)
   Lives in the tabs action area near Share. Click to save now.
   States — saved (green dot), unsaved (amber), saving (animated
   blue), error (red).
   (Ian: "give me an area on the page that shows save details")
   ============================================================ */
body.route-drill #save-status {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 4px 10px;
  border-radius: 999px;
  border: 1px solid var(--dock-line, #e5e7eb);
  background: #fff;
  color: #4b5563;
  font-size: 12px;
  font-weight: 500;
  cursor: pointer;
  user-select: none;
  transition: background 120ms, border-color 120ms, color 120ms;
}
body.route-drill #save-status:hover {
  background: #f9fafb;
  border-color: #d1d5db;
}
body.route-drill .save-status-dot {
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: #10b981;
  flex: 0 0 auto;
}
body.route-drill .save-status--unsaved .save-status-dot { background: #f59e0b; }
body.route-drill .save-status--saving .save-status-dot {
  background: #3b82f6;
  animation: save-status-pulse 1s ease-in-out infinite;
}
body.route-drill .save-status--error {
  border-color: #fecaca;
  background: #fef2f2;
  color: #b91c1c;
}
body.route-drill .save-status--error .save-status-dot { background: #ef4444; }
@keyframes save-status-pulse {
  0%, 100% { opacity: 1; transform: scale(1); }
  50%      { opacity: 0.5; transform: scale(0.7); }
}
@media (max-width: 640px) {
  body.route-drill #save-status .save-status-label { display: none; }
}

/* PLAY (Present) mode button — hidden unless the active drill has
   actual animation frames. Drills with 0 or 1 frame have nothing to
   play back, so the button is a UX dead end. JS toggles
   `body.drill-has-anim` whenever state.animFrames changes.
   (Ian: "only show the play button if there is additional frames in
   the drill") */
body.route-drill:not(.drill-has-anim) #drill-mode-switch button[data-mode="present"] {
  display: none;
}

/* Inline rename on drill tab — when contenteditable is on, give the
   name span a subtle editing affordance so the user knows they're in
   edit mode. (Ian: "can i double click on a drill title in the tab to
   rename?") */
body.route-drill .drill-tab-name.is-editing {
  outline: 2px solid var(--blue, #3b82f6);
  outline-offset: 2px;
  border-radius: 4px;
  background: #fff;
  cursor: text;
  user-select: text;
}

/* Tab switch / new tab loading cue. Spinner on the active tab + slight
   canvas dim so the user sees something is happening between click and
   repaint. Otherwise the tab feels dead during the ~30-100ms switch.
   (Ian: "small lag when i click on a tab ... feels like its dead") */
body.route-drill.drill-tab-switching .drill-tab.active .drill-tab-name::before {
  content: '';
  display: inline-block;
  vertical-align: -2px;
  width: 12px;
  height: 12px;
  margin-right: 6px;
  border: 2px solid rgba(0, 0, 0, 0.18);
  border-top-color: var(--blue, #3b82f6);
  border-radius: 50%;
  animation: drill-tab-spin 0.7s linear infinite;
}
body.route-drill.drill-tab-switching .canvas-stage {
  opacity: 0.55;
  transition: opacity 100ms ease;
  pointer-events: none;
}
body.route-drill:not(.drill-tab-switching) .canvas-stage {
  transition: opacity 180ms ease;
}
@keyframes drill-tab-spin {
  to { transform: rotate(360deg); }
}

/* ============================================================
   Save modal v2 — redesigned 2026-06-15
   (Ian: "can you improve the modal for the save as?")
   ============================================================ */
.save-modal-v2 {
  width: 460px;
  max-width: 92vw;
  padding: 22px 22px 18px;
  border-radius: 14px;
  box-shadow: 0 20px 60px rgba(15, 23, 42, 0.25);
}
.save-modal-v2 .save-modal-head {
  margin-bottom: 18px;
}
.save-modal-v2 h3 {
  margin: 0 0 4px;
  font-size: 20px;
  font-weight: 700;
  letter-spacing: -0.01em;
}
.save-modal-v2 .save-modal-sub {
  margin: 0;
  color: var(--text-dim, #6b7280);
  font-size: 13px;
  line-height: 1.4;
}
.save-modal-v2 .save-modal-section {
  margin-bottom: 14px;
}
.save-modal-v2 .save-modal-section[hidden] {
  display: none;
}
.save-modal-v2 .save-modal-label {
  display: block;
  font-size: 11px;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  font-weight: 600;
  color: var(--text-dim, #6b7280);
  margin: 0 0 6px;
}
.save-modal-v2 .save-modal-label-row {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  margin-bottom: 6px;
}
.save-modal-v2 .save-modal-label-row .save-modal-label { margin: 0; }
.save-modal-v2 .save-modal-hint {
  color: #9ca3af;
  font-size: 10px;
  font-weight: 500;
  text-transform: none;
  letter-spacing: 0;
  margin-left: 4px;
}
.save-modal-v2 .save-modal-folder-count {
  font-size: 11px;
  color: var(--blue, #3b82f6);
  font-weight: 600;
}

/* Segmented control — two stacked cards with radio-driven highlight. */
.save-modal-v2 .seg-control {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 8px;
}
.save-modal-v2 .seg-control--scope { grid-template-columns: 1fr 1fr; }
.save-modal-v2 .seg-item {
  display: block;
  padding: 10px 12px;
  border: 1.5px solid var(--border, #e5e7eb);
  border-radius: 10px;
  cursor: pointer;
  transition: background 130ms ease, border-color 130ms ease;
  position: relative;
}
.save-modal-v2 .seg-item input {
  position: absolute;
  opacity: 0;
  pointer-events: none;
}
.save-modal-v2 .seg-item:hover {
  border-color: #d1d5db;
  background: #f9fafb;
}
.save-modal-v2 .seg-item:has(input:checked) {
  border-color: var(--blue, #3b82f6);
  background: rgba(59, 130, 246, 0.06);
}
.save-modal-v2 .seg-title {
  display: flex;
  align-items: center;
  gap: 6px;
  font-size: 13px;
  font-weight: 600;
  color: #111827;
}
.save-modal-v2 .seg-desc {
  display: block;
  font-size: 11.5px;
  color: var(--text-dim, #6b7280);
  margin-top: 2px;
  font-weight: 400;
}

/* Name input with live character counter. */
.save-modal-v2 .save-modal-name-wrap {
  position: relative;
}
.save-modal-v2 .save-modal-name-wrap input {
  padding-right: 56px;
}
.save-modal-v2 .save-modal-name-count {
  position: absolute;
  right: 10px;
  top: 50%;
  transform: translateY(-50%);
  font-size: 11px;
  color: #9ca3af;
  font-variant-numeric: tabular-nums;
  pointer-events: none;
}
.save-modal-v2 .save-modal-name-count.is-near {
  color: #f59e0b;
}
.save-modal-v2 .save-modal-name-count.is-max {
  color: #ef4444;
}

/* Search above the folder list. */
.save-modal-v2 .save-modal-search {
  margin-bottom: 6px;
}

/* Folder list — custom checkboxes (2026-06-15). Native input is
   visually hidden but still focusable for a11y. A styled box renders
   via the `:checked + span::before` selector. Matches the modal's
   segmented controls: blue accent, rounded corners, smooth hover/
   focus. The whole row stays a <label> so click-anywhere-on-row still
   toggles. (Ian: "the checkboxes in the folders are a little weird")
   Picked via ui-ux-pro-max rules: focus-states, touch-target-size,
   color-contrast 4.5:1, duration 130 ms. */
.save-modal-v2 #modal-folders {
  max-height: 180px;
  overflow-y: auto;
  border: 1px solid var(--border-soft, #f3f4f6);
  border-radius: 8px;
  background: #fafafa;
  padding: 4px;
}
.save-modal-v2 .modal-folder-row {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 7px 9px;
  border-radius: 6px;
  font-size: 13.5px;
  color: #1f2937;
  cursor: pointer;
  user-select: none;
  transition: background 130ms ease, color 130ms ease;
}
.save-modal-v2 .modal-folder-row:hover {
  background: #fff;
}
.save-modal-v2 .modal-folder-row:has(input:checked) {
  background: rgba(59, 130, 246, 0.08);
  color: #111827;
  font-weight: 500;
}
.save-modal-v2 .modal-folder-row.is-hidden {
  display: none;
}
/* Visually hide the native input but keep it in tab order. */
.save-modal-v2 .modal-folder-row input[type="checkbox"] {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  padding: 0;
  overflow: hidden;
  clip: rect(0 0 0 0);
  white-space: nowrap;
  border: 0;
}
/* The span carries the label text AND renders the custom checkbox as
   a ::before pseudo. */
.save-modal-v2 .modal-folder-row > span {
  display: flex;
  align-items: center;
  gap: 10px;
  flex: 1;
  line-height: 1.3;
}
.save-modal-v2 .modal-folder-row > span::before {
  content: '';
  flex: 0 0 auto;
  width: 18px;
  height: 18px;
  border: 1.5px solid #cbd5e1;
  border-radius: 5px;
  background: #fff;
  background-position: center;
  background-repeat: no-repeat;
  background-size: 12px 12px;
  transition: background-color 130ms ease, border-color 130ms ease,
              box-shadow 130ms ease;
}
.save-modal-v2 .modal-folder-row:hover > span::before {
  border-color: #94a3b8;
}
/* Checked: blue fill + white SVG check. Data URI so no extra HTTP. */
.save-modal-v2 .modal-folder-row input:checked + span::before {
  background-color: var(--blue, #3b82f6);
  border-color: var(--blue, #3b82f6);
  background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23ffffff' stroke-width='3.2' stroke-linecap='round' stroke-linejoin='round'><polyline points='5 12.5 10 17 19 7'/></svg>");
}
/* Keyboard focus ring for sighted keyboard users. */
.save-modal-v2 .modal-folder-row input:focus-visible + span::before {
  box-shadow: 0 0 0 3px rgba(59, 130, 246, 0.25);
  border-color: var(--blue, #3b82f6);
}
@media (prefers-reduced-motion: reduce) {
  .save-modal-v2 .modal-folder-row,
  .save-modal-v2 .modal-folder-row > span::before {
    transition: none;
  }
}

/* "Add a new folder" with leading plus icon. */
.save-modal-v2 .save-modal-new-folder {
  display: flex;
  align-items: center;
  gap: 8px;
  border: 1.5px dashed var(--border, #e5e7eb);
  border-radius: 8px;
  padding: 4px 10px;
  margin-top: 8px;
  color: var(--text-dim, #6b7280);
  transition: border-color 120ms ease;
}
.save-modal-v2 .save-modal-new-folder:focus-within {
  border-color: var(--blue, #3b82f6);
  color: var(--blue, #3b82f6);
}
.save-modal-v2 .save-modal-new-folder input {
  border: none;
  background: transparent;
  padding: 8px 0;
  font-size: 13px;
}

/* Action row — larger buttons + Save is the primary blue. */
.save-modal-v2 .modal-actions {
  display: flex;
  gap: 10px;
  justify-content: flex-end;
  margin-top: 18px;
  padding-top: 14px;
  border-top: 1px solid var(--border-soft, #f3f4f6);
}
.save-modal-v2 .modal-actions .btn {
  padding: 9px 18px;
  font-size: 13.5px;
  font-weight: 600;
  border-radius: 8px;
}

/* ============================================================
   Realistic video export — split Export-video button + modal.
   The caret on the right side of the button opens a small menu
   with Diagram (.webm) and Realistic (AI · beta). The modal
   walks the coach through prompt review → submit → poll → play.
   ============================================================ */
.anim-export-group {
  position: relative;
  display: inline-flex;
  align-items: stretch;
  gap: 0;
}
.anim-export-group .anim-export-main {
  border-top-right-radius: 0;
  border-bottom-right-radius: 0;
  padding-right: 10px;
}
.anim-export-group .anim-export-caret {
  border-top-left-radius: 0;
  border-bottom-left-radius: 0;
  padding: 0 6px;
  margin-left: 1px;
  min-width: 22px;
}
.anim-export-group .anim-export-caret svg { width: 12px; height: 12px; }
.anim-export-group .anim-export-caret[aria-expanded="true"] {
  background: rgba(0, 0, 0, 0.06);
}

.anim-export-menu {
  position: absolute;
  bottom: calc(100% + 8px);
  right: 0;
  min-width: 230px;
  background: #fff;
  border: 1px solid rgba(0, 0, 0, 0.08);
  border-radius: 12px;
  box-shadow: 0 14px 32px rgba(0, 0, 0, 0.18);
  padding: 6px;
  z-index: 1200;
  display: flex;
  flex-direction: column;
  gap: 2px;
}
/* When portaled to document.body, switch from absolute (positioned
   relative to .anim-export-group inside the z:36 .anim-panel stacking
   context) to fixed at the viewport level. JS sets left/top from the
   button's getBoundingClientRect; the menu now stacks over the dock,
   topbar, and tab strip. */
.anim-export-menu--portal {
  position: fixed;
  bottom: auto;
  right: auto;
  z-index: 2300;
}
.anim-export-menu[hidden] { display: none; }
.anim-export-item {
  display: flex;
  align-items: center;
  gap: 12px;
  width: 100%;
  padding: 10px 12px;
  border: 0;
  background: transparent;
  border-radius: 8px;
  cursor: pointer;
  text-align: left;
  color: var(--text, #111);
}
.anim-export-item:hover { background: rgba(0, 0, 0, 0.05); }
.anim-export-item-icon {
  width: 28px; height: 28px;
  display: inline-flex; align-items: center; justify-content: center;
  border-radius: 8px;
  background: rgba(0, 0, 0, 0.05);
  color: var(--text, #111);
}
.anim-export-item-icon svg { width: 16px; height: 16px; }
.anim-export-item-pro .anim-export-item-icon {
  background: linear-gradient(135deg, #6c5ce7, #00cec9);
  color: #fff;
}
.anim-export-item-main {
  display: flex; flex-direction: column; gap: 2px;
}
.anim-export-item-title {
  font-weight: 600; font-size: 13px; color: var(--text, #111);
  display: inline-flex; align-items: center; gap: 8px;
}
.anim-export-item-sub {
  font-size: 11px; color: rgba(0, 0, 0, 0.55);
}
.anim-export-beta {
  font-size: 9.5px; letter-spacing: 0.05em; text-transform: uppercase;
  background: linear-gradient(135deg, #6c5ce7, #00cec9);
  color: #fff; padding: 2px 6px; border-radius: 999px; font-weight: 700;
}

/* ---- Modal ---- */
.rv-modal-backdrop {
  position: fixed; inset: 0;
  background: rgba(8, 10, 18, 0.55);
  display: flex; align-items: center; justify-content: center;
  z-index: 2400;
  padding: 24px;
  animation: rv-fade 160ms ease-out;
}
.rv-modal-backdrop[hidden] { display: none; }
@keyframes rv-fade { from { opacity: 0; } to { opacity: 1; } }
body.rv-modal-open { overflow: hidden; }

.rv-modal {
  background: #fff;
  border-radius: 16px;
  width: min(640px, 100%);
  max-height: 90vh;
  overflow: hidden;
  display: flex; flex-direction: column;
  box-shadow: 0 30px 80px rgba(0, 0, 0, 0.3);
  animation: rv-rise 200ms ease-out;
}
@keyframes rv-rise { from { transform: translateY(12px); opacity: 0; } to { transform: translateY(0); opacity: 1; } }

.rv-modal-head {
  padding: 18px 20px 14px;
  border-bottom: 1px solid rgba(0, 0, 0, 0.07);
  display: flex; align-items: center; justify-content: space-between;
}
.rv-modal-head h2 {
  margin: 0;
  font-size: 16px;
  font-weight: 700;
  display: inline-flex; align-items: center; gap: 10px;
  color: var(--text, #111);
}
.rv-modal-icon {
  width: 28px; height: 28px;
  border-radius: 8px;
  display: inline-flex; align-items: center; justify-content: center;
  background: linear-gradient(135deg, #6c5ce7, #00cec9);
  color: #fff;
}
.rv-modal-icon svg { width: 16px; height: 16px; }
.rv-badge {
  font-size: 9.5px; letter-spacing: 0.05em; text-transform: uppercase;
  background: rgba(108, 92, 231, 0.12); color: #6c5ce7;
  padding: 3px 7px; border-radius: 999px; font-weight: 700;
}
.rv-modal-close {
  border: 0; background: transparent; cursor: pointer;
  width: 32px; height: 32px;
  display: inline-flex; align-items: center; justify-content: center;
  border-radius: 8px;
  color: rgba(0, 0, 0, 0.5);
}
.rv-modal-close:hover { background: rgba(0, 0, 0, 0.06); color: var(--text, #111); }
.rv-modal-close svg { width: 16px; height: 16px; }

.rv-modal-body {
  padding: 20px;
  overflow-y: auto;
}

.rv-tagline {
  margin: 0 0 14px;
  font-size: 13.5px;
  color: rgba(0, 0, 0, 0.62);
  line-height: 1.55;
}
.rv-field-label {
  display: block;
  font-size: 11.5px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  color: rgba(0, 0, 0, 0.5);
  margin-bottom: 6px;
}
.rv-prompt {
  width: 100%;
  font: 13.5px/1.55 inherit;
  padding: 12px 14px;
  border-radius: 10px;
  border: 1px solid rgba(0, 0, 0, 0.12);
  resize: vertical;
  min-height: 140px;
  background: #fafbff;
  color: var(--text, #111);
  outline: none;
  transition: border-color 120ms, background 120ms;
}
.rv-prompt:focus {
  border-color: #6c5ce7;
  background: #fff;
  box-shadow: 0 0 0 3px rgba(108, 92, 231, 0.12);
}
.rv-prompt-meta {
  display: flex; justify-content: flex-end;
  font-size: 11.5px; color: rgba(0, 0, 0, 0.45);
  margin-top: 4px;
}
.rv-row {
  display: flex; align-items: center; gap: 12px;
  margin-top: 16px;
}
.rv-row .rv-field-label { margin: 0; }

.rv-segmented {
  display: inline-flex;
  background: rgba(0, 0, 0, 0.05);
  border-radius: 999px;
  padding: 3px;
  gap: 2px;
}
.rv-seg {
  border: 0;
  background: transparent;
  padding: 6px 14px;
  border-radius: 999px;
  font-size: 12.5px;
  font-weight: 600;
  color: rgba(0, 0, 0, 0.6);
  cursor: pointer;
  transition: background 120ms, color 120ms;
}
.rv-seg[aria-pressed="true"] {
  background: #fff;
  color: var(--text, #111);
  box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
}

.rv-footnote {
  margin: 18px 0 0;
  font-size: 11.5px;
  color: rgba(0, 0, 0, 0.5);
  line-height: 1.5;
}

.rv-actions {
  display: flex; justify-content: flex-end; gap: 10px;
  margin-top: 20px;
  padding-top: 14px;
  border-top: 1px solid rgba(0, 0, 0, 0.06);
}
.rv-btn-primary,
.rv-btn-secondary {
  border: 0;
  font: inherit;
  font-size: 13px;
  font-weight: 600;
  padding: 10px 16px;
  border-radius: 10px;
  cursor: pointer;
  display: inline-flex; align-items: center; gap: 8px;
  text-decoration: none;
}
.rv-btn-primary {
  background: linear-gradient(135deg, #6c5ce7, #00cec9);
  color: #fff;
  box-shadow: 0 2px 8px rgba(108, 92, 231, 0.3);
}
.rv-btn-primary:hover { transform: translateY(-1px); box-shadow: 0 4px 14px rgba(108, 92, 231, 0.35); }
.rv-btn-primary svg { width: 14px; height: 14px; }
.rv-btn-secondary {
  background: rgba(0, 0, 0, 0.06);
  color: var(--text, #111);
}
.rv-btn-secondary:hover { background: rgba(0, 0, 0, 0.1); }
.rv-btn-secondary svg { width: 14px; height: 14px; }

.rv-loading, .rv-progress, .rv-result, .rv-error {
  text-align: center;
  padding: 18px 10px;
}
.rv-loading p { margin: 14px 0 0; color: rgba(0, 0, 0, 0.6); font-size: 13.5px; }
.rv-spinner {
  width: 36px; height: 36px;
  border-radius: 50%;
  border: 3px solid rgba(108, 92, 231, 0.2);
  border-top-color: #6c5ce7;
  margin: 0 auto;
  animation: rv-spin 700ms linear infinite;
}
.rv-spinner-lg { width: 52px; height: 52px; border-width: 4px; }
@keyframes rv-spin { to { transform: rotate(360deg); } }

.rv-progress h3 {
  margin: 16px 0 6px;
  font-size: 17px;
  font-weight: 700;
  color: var(--text, #111);
}
.rv-progress-sub {
  margin: 0 auto 18px;
  font-size: 13px; color: rgba(0, 0, 0, 0.6);
  line-height: 1.55;
  max-width: 440px;
}
.rv-progress-bar {
  width: 100%;
  height: 6px;
  border-radius: 999px;
  background: rgba(0, 0, 0, 0.08);
  overflow: hidden;
}
.rv-progress-fill {
  height: 100%;
  background: linear-gradient(90deg, #6c5ce7, #00cec9);
  transition: width 250ms ease-out;
}

.rv-result .rv-video {
  width: 100%;
  border-radius: 12px;
  background: #000;
  display: block;
  box-shadow: 0 6px 24px rgba(0, 0, 0, 0.18);
}
.rv-result-caption {
  margin: 14px 0 0;
  font-size: 13px;
  color: rgba(0, 0, 0, 0.62);
  text-align: center;
}

.rv-error h3 {
  margin: 4px 0 8px;
  font-size: 15px;
  font-weight: 700;
  color: #c0392b;
}
.rv-error p {
  margin: 0;
  font-size: 13px;
  color: rgba(0, 0, 0, 0.7);
  line-height: 1.55;
  text-align: left;
  background: rgba(192, 57, 43, 0.06);
  padding: 12px 14px;
  border-radius: 10px;
  word-break: break-word;
}

@media (max-width: 520px) {
  .rv-modal { max-height: 92vh; border-radius: 14px; }
  .rv-modal-body { padding: 16px; }
  .rv-row { flex-direction: column; align-items: flex-start; }
  .rv-actions { flex-direction: column-reverse; }
  .rv-actions .rv-btn-primary,
  .rv-actions .rv-btn-secondary { width: 100%; justify-content: center; }
}

/* ============================================================
   Drill-board boot overlay — hides the FOUC during the gap
   between HTML parse and tabsRestore. Removed once tabs and
   the active drill have been hydrated from localStorage.
   ============================================================ */
.drill-boot-overlay {
  position: fixed;
  inset: 0;
  background: var(--bg, #f5f6f8);
  display: flex;
  align-items: center;
  justify-content: center;
  z-index: 5000;
  opacity: 1;
  transition: opacity 280ms ease-out;
  pointer-events: auto;
}
.drill-boot-spinner {
  width: 44px;
  height: 44px;
  border-radius: 50%;
  border: 3px solid rgba(0, 0, 0, 0.08);
  border-top-color: var(--accent, #6c5ce7);
  animation: drill-boot-spin 720ms linear infinite;
}
@keyframes drill-boot-spin { to { transform: rotate(360deg); } }
html:not(.rb-booting) .drill-boot-overlay {
  opacity: 0;
  pointer-events: none;
}
/* Hide the rest of the drill UI while booting — overlay covers it,
   but if the user squints/inspects mid-load they shouldn't see the
   half-rendered "Untitled" drill behind. */
html.rb-booting body.route-drill .app { opacity: 0; }
body.route-drill .app { transition: opacity 280ms ease-out; }

/* ============================================================
   Gradient treatment for AI features + state indicators.
   Establishes the "gradient = special / AI / state" pattern
   already used on the Realistic Video icon + stamp palette.
   ============================================================ */

/* --- AI Coach buttons (Adapt / Cues / Critique) ---
   AI features get the purple→teal treatment to brand them as such.
   Override the existing color-mix flat fill via higher specificity
   on the drill-board notes panel. */
body.route-drill .notes-ai-btn,
body.route-drill #panel-notes .notes-ai-btn {
  background: linear-gradient(135deg, #6c5ce7, #00cec9) !important;
  color: #ffffff !important;
  border: none !important;
  box-shadow: 0 1px 2px rgba(108, 92, 231, 0.25);
  transition: transform 120ms, box-shadow 120ms, opacity 120ms;
}
body.route-drill .notes-ai-btn:hover,
body.route-drill #panel-notes .notes-ai-btn:hover {
  background: linear-gradient(135deg, #6c5ce7, #00cec9) !important;
  transform: translateY(-1px);
  box-shadow: 0 4px 12px rgba(108, 92, 231, 0.32);
}
body.route-drill .notes-ai-btn:disabled,
body.route-drill #panel-notes .notes-ai-btn:disabled {
  transform: none;
  box-shadow: none;
}

/* --- Animated-drill badge on drill cards ---
   Was flat blue rgba(30,111,191). Same gradient family as the
   "Blue" stamp swatch so the badge and the player stamps inside
   the thumbnail read as the same brand color. */
.anim-badge {
  background: linear-gradient(135deg, #6c5ce7, #00cec9) !important;
  box-shadow: 0 1px 3px rgba(108, 92, 231, 0.28) !important;
}

/* --- Favorite star (filled state) on drill cards ---
   Was flat red. A warm gold→amber gradient lands closer to
   Apple's filled-star treatment — feels premium, matches the
   yellow swatch family. White star reads cleanly on top. */
.drill-card .fav.fav--on {
  background: linear-gradient(135deg, #fbbf24, #fb923c) !important;
  color: #ffffff !important;
  box-shadow: 0 1px 3px rgba(251, 146, 60, 0.32);
}
.drill-card .fav.fav--on:hover {
  background: linear-gradient(135deg, #fbbf24, #fb923c) !important;
  color: #ffffff !important;
  transform: scale(1.08);
}

/* --- Save status pill (success state) ---
   Default state is "Saved" — promote the green dot into a
   green→lime gradient so the constant attention real estate
   feels alive. Other states (saving/unsaved/error) keep their
   semantic flat color so it's still legible at a glance. */
body.route-drill #save-status:not(.save-status--saving):not(.save-status--unsaved):not(.save-status--error) .save-status-dot {
  background: linear-gradient(135deg, #10b981, #84cc16);
  box-shadow: 0 0 0 2px rgba(16, 185, 129, 0.12);
}

/* ============================================================
   Drill-tab kebab menu — 3-dot per-tab actions (add to plan,
   rename, duplicate). Portaled to body to escape the tab strip's
   stacking context.
   ============================================================ */
.drill-tab-kebab {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 22px;
  height: 22px;
  margin-left: 2px;
  padding: 0;
  background: transparent;
  border: 0;
  border-radius: 6px;
  color: rgba(0, 0, 0, 0.45);
  cursor: pointer;
  transition: background 120ms, color 120ms;
}
.drill-tab-kebab:hover {
  background: rgba(0, 0, 0, 0.07);
  color: var(--text, #111);
}
.drill-tab-kebab svg { width: 16px; height: 16px; }
.drill-tab.active .drill-tab-kebab { color: rgba(0, 0, 0, 0.6); }

.drill-tab-kebab-menu {
  position: fixed;
  min-width: 220px;
  background: #fff;
  border: 1px solid rgba(0, 0, 0, 0.08);
  border-radius: 12px;
  box-shadow: 0 14px 32px rgba(0, 0, 0, 0.18);
  padding: 6px;
  z-index: 2300;
  display: flex;
  flex-direction: column;
  gap: 2px;
  animation: kebab-rise 140ms ease-out;
}
@keyframes kebab-rise { from { opacity: 0; transform: translateY(-4px); } to { opacity: 1; transform: translateY(0); } }
.drill-tab-kebab-menu > button {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 9px 12px;
  background: transparent;
  border: 0;
  border-radius: 8px;
  font: inherit;
  font-size: 13px;
  color: var(--text, #111);
  text-align: left;
  cursor: pointer;
  width: 100%;
}
.drill-tab-kebab-menu > button:hover { background: rgba(0, 0, 0, 0.05); }
.drill-tab-kebab-menu .kebab-item-icon {
  display: inline-flex; align-items: center; justify-content: center;
  width: 26px; height: 26px;
  border-radius: 7px;
  background: rgba(0, 0, 0, 0.05);
  color: rgba(0, 0, 0, 0.7);
}
.drill-tab-kebab-menu .kebab-item-icon svg { width: 15px; height: 15px; }

/* ============================================================
   /drill-share — premium share-link landing page.
   First impression for recipients clicking a coach's emailed
   link. Coachly brand: 135° purple→teal gradient flagship,
   glassmorphism + white surfaces, Geist/system-ui type stack.
   ============================================================ */
body.route-drill-share {
  background:
    radial-gradient(1200px 600px at 12% -10%, rgba(108, 92, 231, 0.10), transparent 60%),
    radial-gradient(1000px 500px at 105% 0%, rgba(0, 206, 201, 0.10), transparent 60%),
    linear-gradient(180deg, #fbfbfd 0%, #f6f7fb 100%);
  min-height: 100vh;
}
.page-drill-share {
  position: relative;
  width: 90%;
  /* Hard cap at 1620px so anything wider than ~1800px viewport stops
     growing — keeps line lengths sane on ultrawides. Below that the
     card stays at 90% of the viewport. */
  max-width: 1620px;
  margin: 0 auto;
  padding: 28px 0 60px;
  display: flex;
  flex-direction: column;
  min-height: 100vh;
}

/* Aurora bloom — subtle background atmosphere so the card floats
   on something, not flat gray. Pointer-events none + behind everything.
   Scales with viewport so the bloom feels right at any width. */
.dshare-aurora {
  position: fixed;
  inset: 0;
  pointer-events: none;
  overflow: hidden;
  z-index: 0;
}
.dshare-aurora-blob {
  position: absolute;
  border-radius: 50%;
  filter: blur(100px);
  opacity: 0.45;
  will-change: transform;
}
.dshare-aurora-blob--a {
  width: 40vw; height: 40vw;
  min-width: 420px; min-height: 420px;
  top: -10vw; left: -10vw;
  background: radial-gradient(circle, #6c5ce7 0%, transparent 65%);
}
.dshare-aurora-blob--b {
  width: 36vw; height: 36vw;
  min-width: 380px; min-height: 380px;
  top: 8vw; right: -8vw;
  background: radial-gradient(circle, #00cec9 0%, transparent 65%);
}
@media (prefers-reduced-motion: reduce) {
  .dshare-aurora-blob { animation: none; }
}

/* Brand mark — centered header. Trust signal for first-time visitors. */
.dshare-brand {
  position: relative;
  z-index: 2;
  margin-bottom: 36px;
  align-self: flex-start;
}
.dshare-brand-link {
  display: inline-flex;
  align-items: center;
  gap: 9px;
  text-decoration: none;
  color: var(--text, #111);
  transition: opacity 150ms;
}
.dshare-brand-link:hover { opacity: 0.75; }
.dshare-brand-mark {
  width: 32px; height: 32px;
  border-radius: 9px;
  background: linear-gradient(135deg, #6c5ce7, #00cec9);
  display: inline-flex; align-items: center; justify-content: center;
  color: #fff;
  box-shadow: 0 4px 12px rgba(108, 92, 231, 0.28);
}
.dshare-brand-mark svg { width: 18px; height: 18px; }
.dshare-brand-text {
  font-size: 16px;
  font-weight: 700;
  letter-spacing: -0.01em;
  color: var(--text, #111);
}

/* Loading state */
.dshare-loading {
  position: relative;
  z-index: 1;
  display: flex; flex-direction: column; align-items: center;
  padding: 80px 20px;
  color: rgba(0, 0, 0, 0.55);
}
.dshare-loading p { margin-top: 16px; font-size: 14px; font-weight: 500; }
.dshare-spinner {
  width: 40px; height: 40px;
  border-radius: 50%;
  border: 3px solid rgba(108, 92, 231, 0.15);
  border-top-color: #6c5ce7;
  animation: dshare-spin 720ms linear infinite;
}
@keyframes dshare-spin { to { transform: rotate(360deg); } }

/* The hero card — two-column landing layout, centered in viewport.
   Thumb on the left, metadata column on the right. Body column gets
   its own scroll if the description is very long so the rink stays
   visible while the recipient reads. */
.dshare-hero {
  position: relative;
  z-index: 1;
  width: 100%;
  display: grid;
  grid-template-columns: minmax(360px, 1.35fr) minmax(340px, 1fr);
  align-items: start;
  gap: 36px;
  background: rgba(255, 255, 255, 0.92);
  backdrop-filter: blur(14px) saturate(160%);
  -webkit-backdrop-filter: blur(14px) saturate(160%);
  border: 1px solid rgba(255, 255, 255, 0.6);
  border-radius: 24px;
  padding: clamp(24px, 2.4vw, 40px);
  box-shadow:
    0 1px 0 rgba(255, 255, 255, 0.8) inset,
    0 30px 60px -20px rgba(17, 24, 39, 0.18),
    0 10px 20px -10px rgba(108, 92, 231, 0.10);
}
.dshare-hero[hidden] { display: none; }

/* Thumb panel — clean white surface, no border, so the rink SVG
   sits flush with the card. Sticky so a long description column
   scrolls past while the rink stays in view. */
.dshare-hero-thumb {
  position: sticky;
  top: 24px;
  width: 100%;
  background: #ffffff;
  border-radius: 18px;
  overflow: hidden;
  aspect-ratio: 16 / 9;
  display: flex; align-items: center; justify-content: center;
}
.dshare-hero-thumb--clickable {
  cursor: zoom-in;
  transition: transform 200ms cubic-bezier(.3, .9, .4, 1.1);
}
.dshare-hero-thumb--clickable:hover img { transform: scale(1.012); }
.dshare-hero-thumb--clickable img { transition: transform 280ms ease; }
.dshare-hero-thumb--clickable:focus-visible {
  outline: 3px solid rgba(108, 92, 231, 0.45);
  outline-offset: 3px;
}

/* Lightbox — click rink to enlarge */
.dshare-lightbox {
  position: fixed;
  inset: 0;
  z-index: 5000;
  display: flex; align-items: center; justify-content: center;
  background: rgba(8, 12, 24, 0.78);
  -webkit-backdrop-filter: blur(12px);
  backdrop-filter: blur(12px);
  padding: 40px;
  opacity: 0;
  transition: opacity 200ms ease-out;
}
.dshare-lightbox[hidden] { display: none; }
.dshare-lightbox--open { opacity: 1; }
.dshare-lightbox-frame {
  position: relative;
  width: 100%;
  height: 100%;
  max-width: 1600px;
  display: flex; align-items: center; justify-content: center;
  transform: scale(0.97);
  transition: transform 280ms cubic-bezier(.3, .9, .4, 1.1);
}
.dshare-lightbox--open .dshare-lightbox-frame { transform: scale(1); }
.dshare-lightbox-frame img {
  max-width: 100%;
  max-height: 100%;
  object-fit: contain;
  border-radius: 18px;
  background: #fff;
  box-shadow: 0 30px 80px rgba(0, 0, 0, 0.45);
}
.dshare-lightbox-close {
  position: absolute;
  top: 20px; right: 20px;
  width: 44px; height: 44px;
  border: 0;
  border-radius: 50%;
  background: rgba(255, 255, 255, 0.10);
  color: #fff;
  display: flex; align-items: center; justify-content: center;
  cursor: pointer;
  transition: background 150ms, transform 150ms;
  z-index: 1;
  -webkit-backdrop-filter: blur(8px);
  backdrop-filter: blur(8px);
}
.dshare-lightbox-close:hover { background: rgba(255, 255, 255, 0.18); transform: scale(1.05); }
.dshare-lightbox-close svg { width: 18px; height: 18px; }

@media (max-width: 720px) {
  .dshare-lightbox { padding: 16px; }
  .dshare-lightbox-close { top: 14px; right: 14px; width: 38px; height: 38px; }
}
.dshare-hero-thumb img {
  width: 100%; height: 100%;
  object-fit: contain;
  display: block;
  position: relative; z-index: 1;
}
.dshare-thumb-glow {
  position: absolute;
  inset: -1px;
  pointer-events: none;
  border-radius: inherit;
  background: linear-gradient(135deg, rgba(108, 92, 231, 0.18), rgba(0, 206, 201, 0.18));
  opacity: 0;
  transition: opacity 260ms;
}
.dshare-hero-thumb:hover .dshare-thumb-glow { opacity: 1; }
.dshare-thumb-badges {
  position: absolute;
  top: 14px; left: 14px;
  display: flex; gap: 6px;
  z-index: 2;
}
.dshare-thumb-badge {
  display: inline-flex; align-items: center; gap: 5px;
  padding: 6px 10px;
  border-radius: 999px;
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.03em;
  color: #fff;
  background: rgba(15, 23, 42, 0.78);
  -webkit-backdrop-filter: blur(8px);
  backdrop-filter: blur(8px);
  box-shadow: 0 4px 10px rgba(0, 0, 0, 0.22);
}
.dshare-thumb-badge svg { width: 11px; height: 11px; }
.dshare-thumb-badge--anim {
  background: linear-gradient(135deg, #6c5ce7, #00cec9);
  box-shadow: 0 4px 12px rgba(108, 92, 231, 0.35);
}

/* Body column — left-aligned next to the thumb. */
.dshare-hero-body {
  display: flex; flex-direction: column;
  min-width: 0;
  padding: 2px 0;
}
.dshare-eyebrow {
  display: inline-flex; align-items: center; gap: 8px;
  font-size: 11px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: rgba(0, 0, 0, 0.45);
  margin-bottom: 12px;
}
.dshare-eyebrow-sep { color: rgba(0, 0, 0, 0.25); }
.dshare-eyebrow-sport {
  background: linear-gradient(135deg, #6c5ce7, #00cec9);
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
  font-weight: 800;
  letter-spacing: 0.06em;
}
.dshare-hero-body h1 {
  margin: 0 0 14px;
  font-size: clamp(26px, 2.2vw, 36px);
  font-weight: 700;
  letter-spacing: -0.02em;
  color: var(--text, #0f172a);
  line-height: 1.15;
  word-wrap: break-word;
}
.dshare-meta-row {
  display: flex; flex-wrap: wrap; gap: 6px;
  margin-bottom: 18px;
}
.dshare-chip {
  display: inline-flex; align-items: center;
  padding: 5px 11px;
  border-radius: 999px;
  background: rgba(15, 23, 42, 0.05);
  border: 1px solid rgba(15, 23, 42, 0.04);
  font-size: 12px;
  font-weight: 600;
  color: rgba(15, 23, 42, 0.78);
}

/* Owner attribution row — avatar + name + handle. Compact pill,
   left-aligned in the body column. */
.dshare-attribution {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  padding: 8px 14px 8px 8px;
  margin-bottom: 18px;
  background: rgba(108, 92, 231, 0.05);
  border: 1px solid rgba(108, 92, 231, 0.12);
  border-radius: 999px;
  align-self: flex-start;
}
.dshare-avatar {
  width: 36px; height: 36px;
  border-radius: 50%;
  background: linear-gradient(135deg, #6c5ce7, #00cec9);
  color: #fff;
  display: inline-flex; align-items: center; justify-content: center;
  font-size: 13px;
  font-weight: 700;
  letter-spacing: 0.02em;
  flex-shrink: 0;
  box-shadow: 0 4px 10px rgba(108, 92, 231, 0.28);
}
.dshare-attribution-body {
  display: inline-flex; align-items: baseline; gap: 6px;
  font-size: 13px;
  line-height: 1.3;
}
.dshare-attribution-label {
  font-size: 11.5px;
  font-weight: 600;
  color: rgba(0, 0, 0, 0.5);
}
.dshare-attribution-name {
  font-weight: 700;
  color: var(--text, #0f172a);
}
.dshare-attribution-handle {
  font-size: 12px;
  color: rgba(0, 0, 0, 0.45);
  font-variant-numeric: tabular-nums;
}

/* Description — left-aligned for natural reading. */
.dshare-description {
  font-size: 14.5px;
  color: rgba(15, 23, 42, 0.75);
  line-height: 1.65;
  margin-bottom: 22px;
  flex: 1;
}
.dshare-description-empty { color: rgba(0, 0, 0, 0.4); font-style: italic; }

/* Sport-mismatch warning */
.dshare-sport-mismatch {
  display: flex; gap: 10px; align-items: flex-start;
  background: linear-gradient(135deg, rgba(251, 191, 36, 0.10), rgba(251, 146, 60, 0.10));
  border: 1px solid rgba(251, 146, 60, 0.25);
  border-radius: 12px;
  padding: 12px 14px;
  font-size: 13px;
  color: #92400e;
  line-height: 1.5;
  margin-bottom: 18px;
}
.dshare-sport-mismatch[hidden] { display: none; }
.dshare-sport-mismatch svg { width: 18px; height: 18px; color: #d97706; flex-shrink: 0; margin-top: 1px; }
.dshare-sport-mismatch strong { color: #78350f; font-weight: 700; }

/* CTA row — left-aligned, pinned to the bottom of the body column. */
.dshare-cta {
  display: flex; gap: 12px; align-items: center;
  margin-top: auto;
}
.dshare-claim-btn {
  position: relative;
  display: inline-flex; align-items: center; gap: 10px;
  padding: 14px 24px;
  background: linear-gradient(135deg, #6c5ce7, #00cec9);
  color: #fff;
  border: 0;
  border-radius: 14px;
  font: inherit;
  font-size: 14.5px;
  font-weight: 700;
  cursor: pointer;
  box-shadow:
    0 1px 0 rgba(255, 255, 255, 0.3) inset,
    0 8px 22px -4px rgba(108, 92, 231, 0.45),
    0 2px 6px rgba(108, 92, 231, 0.18);
  transition: transform 180ms cubic-bezier(.3, .9, .4, 1.1),
              box-shadow 180ms cubic-bezier(.3, .9, .4, 1.1),
              filter 180ms;
  overflow: hidden;
  isolation: isolate;
}
.dshare-claim-btn::before {
  content: '';
  position: absolute; inset: 0;
  background: linear-gradient(120deg, transparent 35%, rgba(255,255,255,0.32) 50%, transparent 65%);
  transform: translateX(-120%);
  transition: transform 600ms cubic-bezier(.3, .9, .4, 1.1);
  pointer-events: none;
  z-index: -1;
}
.dshare-claim-btn:hover {
  transform: translateY(-2px);
  box-shadow:
    0 1px 0 rgba(255, 255, 255, 0.4) inset,
    0 14px 30px -6px rgba(108, 92, 231, 0.55),
    0 4px 10px rgba(108, 92, 231, 0.25);
}
.dshare-claim-btn:hover::before { transform: translateX(120%); }
.dshare-claim-btn:active { transform: translateY(0); }
.dshare-claim-btn:focus-visible {
  outline: 3px solid rgba(108, 92, 231, 0.45);
  outline-offset: 2px;
}
.dshare-claim-btn:disabled { opacity: 0.5; cursor: progress; transform: none; filter: saturate(0.5); }
.dshare-claim-btn svg { width: 18px; height: 18px; }
.dshare-claim-btn--blocked { opacity: 0.7; filter: saturate(0.6); }
.dshare-claim-btn--loading svg { animation: dshare-spin 700ms linear infinite; }

.dshare-cta-secondary {
  font-size: 13.5px;
  font-weight: 500;
  color: rgba(15, 23, 42, 0.55);
  text-decoration: none;
  padding: 10px 14px;
  border-radius: 10px;
  transition: background 150ms, color 150ms;
}
.dshare-cta-secondary:hover {
  color: var(--text, #0f172a);
  background: rgba(15, 23, 42, 0.04);
}
.dshare-cta-secondary:focus-visible {
  outline: 2px solid rgba(108, 92, 231, 0.45);
  outline-offset: 2px;
}

/* Footer mark */
.dshare-footer {
  position: relative;
  z-index: 1;
  margin-top: 40px;
  padding-top: 24px;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  font-size: 12.5px;
  color: rgba(15, 23, 42, 0.5);
}
.dshare-footer strong { color: var(--text, #0f172a); font-weight: 700; }
.dshare-footer-mark {
  width: 18px; height: 18px;
  display: inline-flex; align-items: center; justify-content: center;
  color: rgba(108, 92, 231, 0.85);
}
.dshare-footer-mark svg { width: 16px; height: 16px; }
.dshare-footer-sep { color: rgba(15, 23, 42, 0.25); }
.dshare-footer-link {
  color: rgba(108, 92, 231, 0.85);
  text-decoration: none;
  font-weight: 600;
}
.dshare-footer-link:hover { color: #6c5ce7; text-decoration: underline; }

@media (max-width: 880px) {
  .dshare-hero {
    grid-template-columns: 1fr;
    gap: 22px;
  }
}
@media (max-width: 720px) {
  .page-drill-share { width: 100%; padding: 20px 16px 40px; }
  .dshare-brand { margin-bottom: 24px; }
  .dshare-hero {
    gap: 20px;
    padding: 20px;
    border-radius: 20px;
  }
  .dshare-hero-thumb { aspect-ratio: 16 / 9; }
  .dshare-cta { flex-direction: column-reverse; align-items: stretch; }
  .dshare-claim-btn { justify-content: center; padding: 14px 20px; }
  .dshare-cta-secondary { text-align: center; }
  .dshare-aurora-blob { filter: blur(60px); }
}

/* ============================================================
   Share modal — link tab additions: expiry picker + live stats.
   ============================================================ */
.share-link-expiry {
  display: flex; align-items: center; gap: 10px;
  margin: 8px 0 12px;
  font-size: 12px;
}
.share-link-expiry-label {
  font-size: 11px;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  color: rgba(0, 0, 0, 0.5);
}
.share-link-expiry-segs {
  display: inline-flex;
  background: rgba(0, 0, 0, 0.05);
  border-radius: 999px;
  padding: 3px;
  gap: 2px;
}
.share-link-expiry-seg {
  border: 0;
  background: transparent;
  padding: 5px 12px;
  border-radius: 999px;
  font-size: 12px;
  font-weight: 600;
  color: rgba(0, 0, 0, 0.6);
  cursor: pointer;
  font: inherit;
  font-size: 12px;
}
.share-link-expiry-seg[aria-pressed="true"] {
  background: #fff;
  color: var(--text, #111);
  box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
}

.share-link-stats {
  margin-top: 14px;
  padding-top: 14px;
  border-top: 1px solid rgba(0, 0, 0, 0.07);
}
.share-link-stats-row {
  display: grid;
  grid-template-columns: 1fr 1fr 1fr;
  gap: 10px;
}
.share-link-stat {
  background: rgba(0, 0, 0, 0.03);
  border-radius: 10px;
  padding: 10px 12px;
  text-align: center;
}
.share-link-stat-num {
  display: block;
  font-size: 20px;
  font-weight: 700;
  color: var(--text, #111);
  line-height: 1.1;
  font-variant-numeric: tabular-nums;
}
.share-link-stat-label {
  font-size: 11px;
  font-weight: 500;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  color: rgba(0, 0, 0, 0.5);
  margin-top: 2px;
  display: inline-block;
}
.share-link-stat-expiry .share-link-stat-num { font-size: 17px; }

/* Regenerate button — small icon-only, sits next to the primary Copy
   button. Subtle so it doesn't compete with the main action. */
.share-link-regen {
  display: inline-flex; align-items: center; justify-content: center;
  width: 36px; padding: 0;
  border: 1px solid rgba(0, 0, 0, 0.08);
  background: transparent;
  color: rgba(0, 0, 0, 0.55);
  border-radius: 6px;
  cursor: pointer;
}
.share-link-regen svg { width: 14px; height: 14px; }
.share-link-regen:hover { background: rgba(0, 0, 0, 0.04); color: var(--text, #111); }

/* Polished placeholder when the share snapshot has no thumb.
   Only the placeholder gets a subtle tinted bg — the regular rink
   thumb sits on plain white so the SVG doesn't look framed. */
.dshare-thumb-placeholder {
  display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 12px;
  width: 100%; height: 100%;
  color: rgba(108, 92, 231, 0.55);
  background:
    radial-gradient(circle at 30% 20%, rgba(108, 92, 231, 0.08), transparent 60%),
    radial-gradient(circle at 70% 80%, rgba(0, 206, 201, 0.08), transparent 60%),
    #fafbff;
  font-size: 12.5px;
  font-weight: 600;
  letter-spacing: 0.02em;
}
.dshare-thumb-placeholder svg { width: 44px; height: 44px; opacity: 0.7; }

/* Coach-authored rich-text description — list bullets + spacing */
.dshare-description ul, .dshare-description ol {
  margin: 6px 0; padding-left: 20px;
}
.dshare-description ul { list-style: disc; }
.dshare-description ol { list-style: decimal; }
.dshare-description li { margin: 2px 0; }
.dshare-description p { margin: 6px 0; }
.dshare-description strong { font-weight: 600; }
.dshare-description em { font-style: italic; }

/* ============================================================
   PLANS LANDING — premium ui-ux-pro-max polish pass.
   Overrides the legacy clipboard skeuomorphism with a modern
   card system that matches the Coachly brand language
   (135° purple→teal gradient, glassmorphism, polished CTAs).
   Appended last so all rules win without selector wars.
   ============================================================ */

/* Page background — subtle aurora to match the share view's vibe */
body.route-plans {
  background:
    radial-gradient(900px 500px at 8% -8%, rgba(108, 92, 231, 0.07), transparent 60%),
    radial-gradient(800px 460px at 102% 5%, rgba(0, 206, 201, 0.07), transparent 60%),
    linear-gradient(180deg, #fbfbfd 0%, #f6f7fb 100%);
}

/* Page header — bigger headline, gradient brand mark */
.plans-page .page-header {
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
  gap: 16px;
  padding: 4px 0 6px;
  margin-bottom: 22px;
}
.plans-page .page-header h1 {
  font-size: 28px !important;
  font-weight: 700;
  letter-spacing: -0.02em;
  line-height: 1.15;
  margin: 0 0 4px;
  color: var(--text, #0f172a);
  display: inline-flex;
  align-items: center;
  gap: 12px;
}
.plans-page .page-header h1::before {
  content: '';
  width: 36px; height: 36px;
  border-radius: 10px;
  background: linear-gradient(135deg, #6c5ce7, #00cec9);
  background-image:
    linear-gradient(135deg, transparent 30%, rgba(255,255,255,0.18) 50%, transparent 70%),
    linear-gradient(135deg, #6c5ce7, #00cec9);
  box-shadow: 0 4px 14px rgba(108, 92, 231, 0.28);
  flex-shrink: 0;
  position: relative;
}
.plans-page .page-header h1::after {
  content: '';
  position: absolute;
  left: 8px; top: 9px;
  width: 18px; height: 18px;
  background: no-repeat center / contain url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='white' stroke-width='2.2' stroke-linecap='round' stroke-linejoin='round'><rect x='3' y='5' width='18' height='16' rx='2'/><path d='M16 3v4M8 3v4M3 11h18M8 15h3M8 18h6'/></svg>");
}
.plans-page .page-header .sub {
  font-size: 13.5px;
  color: rgba(15, 23, 42, 0.55);
  margin: 0;
}

/* Action buttons up top — AI gets brand gradient, New Plan gets soft outlined */
.plans-page .page-actions { display: flex; gap: 10px; }
.plans-page #btn-ai-plan {
  padding: 9px 16px !important;
  border: 0 !important;
  border-radius: 11px !important;
  background: linear-gradient(135deg, #6c5ce7, #00cec9) !important;
  color: #fff !important;
  font-weight: 700 !important;
  font-size: 13px !important;
  box-shadow: 0 6px 18px -4px rgba(108, 92, 231, 0.42), 0 2px 6px rgba(108, 92, 231, 0.18) !important;
  transition: transform 160ms, box-shadow 160ms !important;
}
.plans-page #btn-ai-plan:hover { transform: translateY(-1px); box-shadow: 0 10px 24px -6px rgba(108, 92, 231, 0.52) !important; }
.plans-page #btn-ai-plan svg { stroke: #fff; opacity: 0.95; }
.plans-page #btn-new-plan {
  padding: 9px 18px !important;
  border-radius: 11px !important;
  background: #fff !important;
  color: var(--text, #0f172a) !important;
  border: 1px solid rgba(15, 23, 42, 0.12) !important;
  font-weight: 700 !important;
  font-size: 13px !important;
  box-shadow: 0 2px 6px rgba(15, 23, 42, 0.06) !important;
  transition: transform 160ms, box-shadow 160ms, border-color 160ms !important;
}
.plans-page #btn-new-plan:hover {
  border-color: rgba(108, 92, 231, 0.40) !important;
  box-shadow: 0 6px 16px -4px rgba(108, 92, 231, 0.22) !important;
  transform: translateY(-1px);
}

/* Toolbar — glass card */
.plans-page .plans-toolbar {
  background: rgba(255, 255, 255, 0.92);
  border: 1px solid rgba(15, 23, 42, 0.06);
  border-radius: 16px;
  padding: 16px;
  margin-bottom: 28px;
  box-shadow: 0 1px 0 rgba(255, 255, 255, 0.8) inset, 0 6px 20px -8px rgba(15, 23, 42, 0.08);
  backdrop-filter: blur(10px) saturate(140%);
  -webkit-backdrop-filter: blur(10px) saturate(140%);
}
.plans-page .plans-search { position: relative; }
.plans-page .plans-search input {
  width: 100%;
  padding: 12px 14px 12px 42px;
  font: inherit;
  font-size: 14px;
  background: #fafbff;
  border: 1px solid rgba(15, 23, 42, 0.10);
  border-radius: 12px;
  color: var(--text, #0f172a);
  transition: border-color 150ms, box-shadow 150ms, background 150ms;
  outline: 0;
}
.plans-page .plans-search input::placeholder { color: rgba(15, 23, 42, 0.42); }
.plans-page .plans-search input:focus {
  border-color: #6c5ce7;
  background: #fff;
  box-shadow: 0 0 0 3px rgba(108, 92, 231, 0.14);
}
.plans-page .plans-search-icon {
  position: absolute;
  left: 14px; top: 50%;
  width: 16px; height: 16px;
  transform: translateY(-50%);
  color: rgba(15, 23, 42, 0.45);
  pointer-events: none;
}
.plans-page .plans-toolbar-row {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 12px;
  flex-wrap: wrap;
  margin-top: 14px;
}
.plans-page .plans-book-filters {
  display: flex; flex-wrap: wrap; gap: 6px;
}
.plans-page .plans-book-chip {
  display: inline-flex; align-items: center; gap: 6px;
  padding: 6px 12px;
  border: 1px solid rgba(15, 23, 42, 0.10);
  background: #fff;
  border-radius: 999px;
  font: inherit;
  font-size: 12.5px;
  font-weight: 600;
  color: rgba(15, 23, 42, 0.65);
  cursor: pointer;
  transition: background 150ms, border-color 150ms, color 150ms, transform 120ms;
}
.plans-page .plans-book-chip:hover {
  border-color: rgba(108, 92, 231, 0.30);
  color: var(--text, #0f172a);
  transform: translateY(-1px);
}
.plans-page .plans-book-chip.is-active {
  background: linear-gradient(135deg, #6c5ce7, #00cec9);
  border-color: transparent;
  color: #fff;
  box-shadow: 0 4px 12px -2px rgba(108, 92, 231, 0.42);
}
.plans-page .plans-book-chip-count {
  display: inline-flex; align-items: center; justify-content: center;
  min-width: 18px; height: 18px; padding: 0 5px;
  border-radius: 999px;
  background: rgba(15, 23, 42, 0.06);
  color: rgba(15, 23, 42, 0.60);
  font-size: 10.5px;
  font-weight: 700;
  font-variant-numeric: tabular-nums;
}
.plans-page .plans-book-chip.is-active .plans-book-chip-count {
  background: rgba(255, 255, 255, 0.22);
  color: #fff;
}
.plans-page .plans-sort { display: flex; align-items: center; gap: 8px; }
.plans-page .plans-sort-label {
  font-size: 11.5px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  color: rgba(15, 23, 42, 0.5);
}
.plans-page .plans-sort-select {
  padding: 8px 32px 8px 12px;
  border: 1px solid rgba(15, 23, 42, 0.10);
  border-radius: 10px;
  background: #fafbff no-repeat right 10px center / 12px url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%2364748b' stroke-width='2.4' stroke-linecap='round'><polyline points='6 9 12 15 18 9'/></svg>");
  font: inherit;
  font-size: 13px;
  font-weight: 600;
  color: var(--text, #0f172a);
  cursor: pointer;
  appearance: none;
  -webkit-appearance: none;
  transition: border-color 150ms, background-color 150ms;
}
.plans-page .plans-sort-select:hover { border-color: rgba(108, 92, 231, 0.30); }
.plans-page .plans-sort-select:focus { outline: 0; border-color: #6c5ce7; box-shadow: 0 0 0 3px rgba(108, 92, 231, 0.14); }

/* Shelves */
.plans-page #plan-grid { padding-top: 0; }
.plans-page .plans-shelf { margin-bottom: 36px; }
.plans-page .plans-shelf-head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  margin-bottom: 14px;
  padding-bottom: 12px;
  border-bottom: 1px solid rgba(15, 23, 42, 0.06);
}
.plans-page .plans-shelf-title {
  font-size: 14px !important;
  font-weight: 700;
  letter-spacing: -0.005em;
  color: var(--text, #0f172a);
  text-transform: uppercase;
  letter-spacing: 0.08em;
  font-size: 12.5px !important;
  margin: 0;
}
.plans-page .plans-shelf-count {
  font-size: 12px;
  font-weight: 600;
  color: rgba(15, 23, 42, 0.45);
  font-variant-numeric: tabular-nums;
}
.plans-page .plans-shelf-floor { display: none; }
.plans-page .plans-shelf-row {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
  gap: 18px;
  align-items: stretch;
}

/* Plan card — modern, premium, gradient-aware. Override all the
   skeuomorphic clipboard styles defined earlier. */
.plans-page .plan-clip {
  all: unset;
  display: flex;
  flex-direction: column;
  position: relative;
  background: rgba(255, 255, 255, 0.96);
  border: 1px solid rgba(15, 23, 42, 0.07);
  border-radius: 16px;
  overflow: hidden;
  cursor: pointer;
  min-height: 240px;
  transition: transform 200ms cubic-bezier(.3, .9, .4, 1.1),
              box-shadow 200ms cubic-bezier(.3, .9, .4, 1.1),
              border-color 200ms;
  box-shadow:
    0 1px 0 rgba(255, 255, 255, 0.8) inset,
    0 1px 2px rgba(15, 23, 42, 0.05),
    0 6px 16px -8px rgba(15, 23, 42, 0.10);
}
.plans-page .plan-clip:hover {
  transform: translateY(-3px);
  border-color: rgba(108, 92, 231, 0.20);
  box-shadow:
    0 1px 0 rgba(255, 255, 255, 0.9) inset,
    0 2px 4px rgba(15, 23, 42, 0.06),
    0 18px 36px -10px rgba(108, 92, 231, 0.20),
    0 6px 16px -6px rgba(15, 23, 42, 0.10);
}
.plans-page .plan-clip:focus-visible {
  outline: 3px solid rgba(108, 92, 231, 0.40);
  outline-offset: 3px;
}

/* Gradient accent strip on top */
.plans-page .plan-clip::before {
  content: '';
  position: absolute;
  top: 0; left: 0; right: 0;
  height: 3px;
  background: linear-gradient(90deg, #6c5ce7, #00cec9);
  z-index: 1;
}
.plans-page .plan-clip::after { display: none; }

/* Player-visible variant gets a green accent */
.plans-page .plan-clip--shared::before {
  background: linear-gradient(90deg, #10b981, #84cc16);
}
.plans-page .plan-clip--upcoming::before {
  background: linear-gradient(90deg, #f59e0b, #ec4899);
}

/* Strip out the old clipboard parts */
.plans-page .plan-clip-top { display: none; }
.plans-page .plan-clip-clip { display: none; }

/* Page (the body) */
.plans-page .plan-clip-page {
  display: flex;
  flex-direction: column;
  flex: 1;
  padding: 18px 16px 14px;
  background: none;
  position: relative;
}
.plans-page .plan-clip-page-title {
  display: flex;
  align-items: center;
  gap: 8px;
  font-size: 15.5px;
  font-weight: 700;
  letter-spacing: -0.01em;
  line-height: 1.25;
  color: var(--text, #0f172a);
  margin-bottom: 6px;
  min-height: 24px;
}
.plans-page .plan-clip-page-title span {
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}
.plans-page .plan-clip-dot {
  width: 8px; height: 8px;
  border-radius: 50%;
  flex-shrink: 0;
}
.plans-page .plan-clip-dot--visible { background: linear-gradient(135deg, #10b981, #84cc16); box-shadow: 0 0 0 2px rgba(16, 185, 129, 0.15); }
.plans-page .plan-clip-dot--private { background: rgba(15, 23, 42, 0.35); }
.plans-page .plan-clip-page-meta {
  font-size: 12px;
  font-weight: 600;
  color: rgba(15, 23, 42, 0.55);
  margin-bottom: 12px;
  font-variant-numeric: tabular-nums;
}

/* Sport diagram panel inside the card */
.plans-page .plan-clip-page-diagram {
  background: linear-gradient(135deg, #f8f9fc, #eef0f6);
  border: 1px solid rgba(15, 23, 42, 0.05);
  border-radius: 11px;
  aspect-ratio: 16 / 9;
  display: flex; align-items: center; justify-content: center;
  margin-bottom: 12px;
  overflow: hidden;
  padding: 8px;
}
.plans-page .plan-clip-page-diagram svg {
  max-width: 100%;
  max-height: 100%;
  width: auto; height: auto;
  opacity: 0.85;
}

/* Upcoming pill */
.plans-page .plan-clip-upcoming {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  align-self: flex-start;
  padding: 4px 10px;
  border-radius: 999px;
  background: linear-gradient(135deg, rgba(245, 158, 11, 0.14), rgba(236, 72, 153, 0.14));
  border: 1px solid rgba(245, 158, 11, 0.30);
  color: #92400e;
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.02em;
  margin-bottom: 10px;
}
.plans-page .plan-clip-upcoming svg { width: 11px; height: 11px; }

/* Footer with book + date */
.plans-page .plan-clip-foot {
  margin-top: auto;
  padding: 10px 16px;
  background: rgba(15, 23, 42, 0.03);
  border-top: 1px solid rgba(15, 23, 42, 0.06);
}
.plans-page .plan-clip-meta {
  font-size: 11.5px;
  font-weight: 600;
  color: rgba(15, 23, 42, 0.55);
  letter-spacing: 0.02em;
}

/* Actions overlay — revealed on hover, glass mini-buttons */
.plans-page .plan-clip-actions {
  position: absolute;
  top: 12px; right: 12px;
  display: flex;
  gap: 4px;
  opacity: 0;
  transform: translateY(-2px);
  transition: opacity 180ms, transform 180ms;
  z-index: 2;
}
.plans-page .plan-clip:hover .plan-clip-actions,
.plans-page .plan-clip:focus-within .plan-clip-actions { opacity: 1; transform: translateY(0); }
.plans-page .plan-clip-action {
  width: 30px; height: 30px;
  border: 0;
  border-radius: 8px;
  background: rgba(255, 255, 255, 0.92);
  color: rgba(15, 23, 42, 0.55);
  display: inline-flex; align-items: center; justify-content: center;
  cursor: pointer;
  transition: background 150ms, color 150ms, transform 150ms;
  -webkit-backdrop-filter: blur(8px);
  backdrop-filter: blur(8px);
  box-shadow: 0 2px 6px rgba(15, 23, 42, 0.10);
}
.plans-page .plan-clip-action svg { width: 14px; height: 14px; }
.plans-page .plan-clip-action--share:hover {
  background: linear-gradient(135deg, #6c5ce7, #00cec9);
  color: #fff;
  transform: scale(1.05);
}
.plans-page .plan-clip-action--del:hover {
  background: #ef4444;
  color: #fff;
  transform: scale(1.05);
}
.plans-page .plan-clip-action--run:hover {
  background: linear-gradient(135deg, #10b981, #84cc16);
  color: #fff;
  transform: scale(1.05);
}

/* Empty state — bigger icon with gradient ring */
.plans-page #plan-grid .empty {
  text-align: center;
  padding: 80px 24px;
  background: rgba(255, 255, 255, 0.6);
  border: 1px dashed rgba(15, 23, 42, 0.12);
  border-radius: 18px;
  color: rgba(15, 23, 42, 0.55);
  font-size: 14px;
  line-height: 1.6;
}
.plans-page #plan-grid .empty .icon {
  display: inline-flex;
  align-items: center; justify-content: center;
  width: 64px; height: 64px;
  margin: 0 auto 18px;
  background: linear-gradient(135deg, #6c5ce7, #00cec9);
  border-radius: 18px;
  box-shadow: 0 8px 24px -6px rgba(108, 92, 231, 0.40);
}
.plans-page #plan-grid .empty .icon svg {
  width: 28px !important;
  height: 28px !important;
  color: #fff !important;
}
.plans-page #plan-grid .empty b { color: var(--text, #0f172a); font-weight: 700; }

/* Mobile */
@media (max-width: 720px) {
  .plans-page .page-header { flex-direction: column; align-items: flex-start; gap: 14px; }
  .plans-page .page-actions { width: 100%; }
  .plans-page .page-actions .btn { flex: 1; justify-content: center; }
  .plans-page .plans-shelf-row { grid-template-columns: 1fr; }
}

/* ============================================================
   PLANS LANDING — v2: team-color gradient + real drill artwork.
   - Gradients now pull from --brand-primary/--brand-secondary
     (team colors), falling back to Coachly purple→teal when a
     team hasn't picked colors.
   - Plan card hero is the FIRST drill's actual thumbnail (Xs &
     Os + arrows the coach drew).
   ============================================================ */
:root {
  --plans-grad-from: var(--brand-primary, #6c5ce7);
  --plans-grad-to:   var(--brand-secondary, #00cec9);
}

/* Re-skin the page mark + buttons + chips to use team colors. */
.plans-page .page-header h1::before {
  background: linear-gradient(135deg, var(--plans-grad-from), var(--plans-grad-to));
  background-image:
    linear-gradient(135deg, transparent 30%, rgba(255,255,255,0.18) 50%, transparent 70%),
    linear-gradient(135deg, var(--plans-grad-from), var(--plans-grad-to));
  box-shadow: 0 4px 14px color-mix(in srgb, var(--plans-grad-from) 35%, transparent);
}
.plans-page #btn-ai-plan {
  background: linear-gradient(135deg, var(--plans-grad-from), var(--plans-grad-to)) !important;
  box-shadow:
    0 6px 18px -4px color-mix(in srgb, var(--plans-grad-from) 45%, transparent),
    0 2px 6px color-mix(in srgb, var(--plans-grad-from) 25%, transparent) !important;
}
.plans-page #btn-ai-plan:hover {
  box-shadow: 0 10px 24px -6px color-mix(in srgb, var(--plans-grad-from) 55%, transparent) !important;
}
.plans-page #btn-new-plan:hover {
  border-color: color-mix(in srgb, var(--plans-grad-from) 40%, transparent) !important;
  box-shadow: 0 6px 16px -4px color-mix(in srgb, var(--plans-grad-from) 22%, transparent) !important;
}
.plans-page .plans-search input:focus {
  border-color: var(--plans-grad-from);
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--plans-grad-from) 16%, transparent);
}
.plans-page .plans-book-chip:hover {
  border-color: color-mix(in srgb, var(--plans-grad-from) 32%, transparent);
}
.plans-page .plans-book-chip.is-active {
  background: linear-gradient(135deg, var(--plans-grad-from), var(--plans-grad-to));
  box-shadow: 0 4px 12px -2px color-mix(in srgb, var(--plans-grad-from) 45%, transparent);
}
.plans-page .plans-sort-select:hover {
  border-color: color-mix(in srgb, var(--plans-grad-from) 32%, transparent);
}
.plans-page .plans-sort-select:focus {
  border-color: var(--plans-grad-from);
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--plans-grad-from) 16%, transparent);
}

/* Card top accent + hover tint — pull team colors */
.plans-page .plan-clip::before {
  background: linear-gradient(90deg, var(--plans-grad-from), var(--plans-grad-to));
}
.plans-page .plan-clip:hover {
  border-color: color-mix(in srgb, var(--plans-grad-from) 24%, transparent);
  box-shadow:
    0 1px 0 rgba(255, 255, 255, 0.9) inset,
    0 2px 4px rgba(15, 23, 42, 0.06),
    0 18px 36px -10px color-mix(in srgb, var(--plans-grad-from) 24%, transparent),
    0 6px 16px -6px rgba(15, 23, 42, 0.10);
}
.plans-page .plan-clip:focus-visible {
  outline: 3px solid color-mix(in srgb, var(--plans-grad-from) 44%, transparent);
}

/* Hero — real drill thumbnail at the top of the card */
.plans-page .plan-clip {
  padding: 0;        /* hero + page sections own their own padding */
  min-height: 0;     /* let content drive height */
}
.plans-page .plan-clip-hero {
  position: relative;
  aspect-ratio: 16 / 9;
  width: 100%;
  background:
    linear-gradient(180deg, rgba(15, 23, 42, 0.02), transparent 40%),
    #ffffff;
  border-bottom: 1px solid color-mix(in srgb, var(--plans-grad-from) 8%, rgba(15, 23, 42, 0.05));
  overflow: hidden;
  display: flex; align-items: center; justify-content: center;
}
.plans-page .plan-clip-hero-thumb {
  width: 100%; height: 100%;
  object-fit: contain;
  display: block;
  transition: transform 280ms cubic-bezier(.3, .9, .4, 1.1);
}
.plans-page .plan-clip:hover .plan-clip-hero-thumb { transform: scale(1.025); }
.plans-page .plan-clip-hero-fallback {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 100%; height: 100%;
  padding: 14px;
  color: color-mix(in srgb, var(--plans-grad-from) 75%, #475569);
  background:
    radial-gradient(circle at 30% 20%, color-mix(in srgb, var(--plans-grad-from) 9%, transparent), transparent 60%),
    radial-gradient(circle at 70% 80%, color-mix(in srgb, var(--plans-grad-to) 9%, transparent), transparent 60%),
    linear-gradient(135deg, #f8f9fc, #eef0f6);
}
.plans-page .plan-clip-hero-fallback svg {
  max-width: 100%;
  max-height: 100%;
  opacity: 0.7;
}

/* "+N" badge top-right of the hero when there are multiple drills */
.plans-page .plan-clip-hero-stack {
  position: absolute;
  top: 12px; left: 12px;
  background: linear-gradient(135deg, var(--plans-grad-from), var(--plans-grad-to));
  color: #fff;
  padding: 5px 10px;
  border-radius: 999px;
  font-size: 11px;
  font-weight: 800;
  letter-spacing: 0.02em;
  box-shadow: 0 4px 10px color-mix(in srgb, var(--plans-grad-from) 35%, transparent);
}

/* Upcoming pill sits below the stack badge on the hero */
.plans-page .plan-clip-hero .plan-clip-upcoming {
  position: absolute;
  bottom: 12px; left: 12px;
  margin: 0;
}

/* Actions overlay — top-right of the hero */
.plans-page .plan-clip-actions { top: 10px; right: 10px; }

/* Page (body) — title + meta below the hero */
.plans-page .plan-clip-page {
  padding: 14px 16px 8px;
}
.plans-page .plan-clip-page-title {
  margin-bottom: 4px;
}
.plans-page .plan-clip-page-meta {
  margin-bottom: 10px;
}

/* Footer — subtle team-color tinted background */
.plans-page .plan-clip-foot {
  background: color-mix(in srgb, var(--plans-grad-from) 5%, #fafbff);
  border-top: 1px solid color-mix(in srgb, var(--plans-grad-from) 10%, rgba(15, 23, 42, 0.05));
}

/* Empty state — gradient icon disc pulls team color */
.plans-page #plan-grid .empty .icon {
  background: linear-gradient(135deg, var(--plans-grad-from), var(--plans-grad-to));
  box-shadow: 0 8px 24px -6px color-mix(in srgb, var(--plans-grad-from) 40%, transparent);
}

/* Aurora bloom in team colors */
body.route-plans {
  background:
    radial-gradient(900px 500px at 8% -8%, color-mix(in srgb, var(--plans-grad-from) 8%, transparent), transparent 60%),
    radial-gradient(800px 460px at 102% 5%, color-mix(in srgb, var(--plans-grad-to) 8%, transparent), transparent 60%),
    linear-gradient(180deg, #fbfbfd 0%, #f6f7fb 100%);
}

/* ============================================================
   PLANS v3 — color-saturated plan cards.
   The plan card itself becomes the team's primary color (with a
   gradient to a complementary tone). Title gets bigger + bolder.
   Thumbnail stays white so the drill diagram reads cleanly.
   ============================================================ */

/* Derive a "to" stop when the team only has a primary color set.
   color-mix in oklch gives a perceptually-lighter version of the
   primary (cleaner than RGB mixing on saturated colors). */
:root {
  --plans-grad-from: var(--brand-primary, #6c5ce7);
  --plans-grad-to:   var(--brand-secondary, color-mix(in oklch, var(--brand-primary, #6c5ce7) 55%, white));
}

/* Card body now PAINTS in team color — not just the accent strip. */
.plans-page .plan-clip {
  background: linear-gradient(155deg, var(--plans-grad-from), var(--plans-grad-to)) !important;
  border-color: color-mix(in srgb, var(--plans-grad-from) 60%, transparent) !important;
  box-shadow:
    0 1px 0 rgba(255, 255, 255, 0.18) inset,
    0 2px 4px color-mix(in srgb, var(--plans-grad-from) 18%, transparent),
    0 14px 30px -10px color-mix(in srgb, var(--plans-grad-from) 36%, transparent) !important;
}
.plans-page .plan-clip:hover {
  border-color: color-mix(in srgb, var(--plans-grad-from) 75%, transparent) !important;
  box-shadow:
    0 1px 0 rgba(255, 255, 255, 0.22) inset,
    0 4px 6px color-mix(in srgb, var(--plans-grad-from) 22%, transparent),
    0 28px 50px -12px color-mix(in srgb, var(--plans-grad-from) 50%, transparent) !important;
}

/* Drop the old accent-strip — the whole card is the accent now. */
.plans-page .plan-clip::before { display: none; }

/* Hero panel — keep white so the rink + Xs/Os read cleanly. */
.plans-page .plan-clip-hero {
  background: #ffffff;
  border-bottom: 0;
  margin: 6px 6px 0;
  border-radius: 11px;
  box-shadow: 0 1px 2px rgba(15, 23, 42, 0.10);
}
.plans-page .plan-clip-hero-fallback {
  background:
    radial-gradient(circle at 30% 20%, color-mix(in srgb, var(--plans-grad-from) 10%, transparent), transparent 60%),
    radial-gradient(circle at 70% 80%, color-mix(in srgb, var(--plans-grad-to) 10%, transparent), transparent 60%),
    linear-gradient(135deg, #f8f9fc, #eef0f6);
}

/* "+N" stack badge — now white pill on the colored card */
.plans-page .plan-clip-hero-stack {
  background: rgba(255, 255, 255, 0.95);
  color: color-mix(in srgb, var(--plans-grad-from) 80%, #0f172a);
  box-shadow: 0 2px 6px rgba(15, 23, 42, 0.18);
}

/* Title section — light text on the colored body. Bigger + bolder. */
.plans-page .plan-clip-page {
  padding: 14px 18px 12px;
}
.plans-page .plan-clip-page-title {
  font-size: 19px !important;
  font-weight: 800 !important;
  color: #ffffff !important;
  letter-spacing: -0.015em;
  line-height: 1.18;
  margin-bottom: 6px;
  text-shadow: 0 1px 2px rgba(0, 0, 0, 0.12);
}
.plans-page .plan-clip-page-meta {
  font-size: 12.5px;
  font-weight: 600;
  color: rgba(255, 255, 255, 0.82) !important;
  letter-spacing: 0.01em;
}
.plans-page .plan-clip-dot--visible {
  background: #ffffff;
  box-shadow: 0 0 0 2px rgba(255, 255, 255, 0.25);
}
.plans-page .plan-clip-dot--private {
  background: rgba(255, 255, 255, 0.5);
}

/* Footer — darker tint over the gradient for hierarchy */
.plans-page .plan-clip-foot {
  background: rgba(0, 0, 0, 0.18);
  border-top: 1px solid rgba(255, 255, 255, 0.10);
}
.plans-page .plan-clip-meta {
  color: rgba(255, 255, 255, 0.88) !important;
  font-weight: 600;
  letter-spacing: 0.03em;
}

/* Upcoming pill on the colored hero — needs higher contrast now */
.plans-page .plan-clip-hero .plan-clip-upcoming {
  background: linear-gradient(135deg, rgba(255, 255, 255, 0.96), rgba(255, 255, 255, 0.88));
  border-color: rgba(255, 255, 255, 0.6);
  color: color-mix(in srgb, var(--plans-grad-from) 85%, #0f172a);
  box-shadow: 0 2px 6px rgba(15, 23, 42, 0.15);
}

/* Actions overlay — glass white on the colored body */
.plans-page .plan-clip-action {
  background: rgba(255, 255, 255, 0.94);
  color: color-mix(in srgb, var(--plans-grad-from) 80%, #0f172a);
}
.plans-page .plan-clip-action--share:hover {
  background: #ffffff;
  color: var(--plans-grad-from);
}
.plans-page .plan-clip-action--run:hover {
  background: linear-gradient(135deg, #10b981, #84cc16);
  color: #ffffff;
}
.plans-page .plan-clip-action--del:hover {
  background: #ef4444;
  color: #ffffff;
}

/* ============================================================
   PLANS v4 — text-first card design, no artwork.
   Drill preview list anchors the card; bigger bolder title;
   tight info hierarchy.  Card body still paints in team color.
   ============================================================ */
.plans-page .plan-clip {
  display: flex;
  flex-direction: column;
  position: relative;
  padding: 20px 22px 18px;
  background: linear-gradient(155deg, var(--plans-grad-from), var(--plans-grad-to)) !important;
  border: 1px solid color-mix(in srgb, var(--plans-grad-from) 55%, transparent) !important;
  border-radius: 18px;
  overflow: hidden;
  cursor: pointer;
  transition: transform 220ms cubic-bezier(.3, .9, .4, 1.1),
              box-shadow 220ms cubic-bezier(.3, .9, .4, 1.1),
              border-color 220ms;
  box-shadow:
    0 1px 0 rgba(255, 255, 255, 0.18) inset,
    0 1px 3px color-mix(in srgb, var(--plans-grad-from) 22%, transparent),
    0 14px 32px -12px color-mix(in srgb, var(--plans-grad-from) 40%, transparent) !important;
  min-height: 0;
}
.plans-page .plan-clip:hover {
  transform: translateY(-3px);
  box-shadow:
    0 1px 0 rgba(255, 255, 255, 0.22) inset,
    0 2px 4px color-mix(in srgb, var(--plans-grad-from) 28%, transparent),
    0 26px 52px -16px color-mix(in srgb, var(--plans-grad-from) 56%, transparent) !important;
}
.plans-page .plan-clip:focus-visible {
  outline: 3px solid color-mix(in srgb, var(--plans-grad-from) 48%, transparent);
  outline-offset: 3px;
}
.plans-page .plan-clip::before { display: none; }
.plans-page .plan-clip::after { display: none; }

/* Subtle gradient sheen at the top — gives the card a polished
   "premium plastic" highlight without the old skeu clip illustration. */
.plans-page .plan-clip > .plan-clip-actions { z-index: 2; }
.plans-page .plan-clip > .plan-clip-eyebrow,
.plans-page .plan-clip > .plan-clip-name,
.plans-page .plan-clip > .plan-clip-stats,
.plans-page .plan-clip > .plan-clip-pill-row,
.plans-page .plan-clip > .plan-clip-drills,
.plans-page .plan-clip > .plan-clip-empty {
  position: relative; z-index: 1;
}

/* Eyebrow — visibility dot + book + date */
.plans-page .plan-clip-eyebrow {
  display: flex; align-items: center; gap: 8px;
  font-size: 10.5px;
  font-weight: 800;
  letter-spacing: 0.10em;
  text-transform: uppercase;
  color: rgba(255, 255, 255, 0.85);
  margin-bottom: 10px;
  min-height: 14px;
}
.plans-page .plan-clip-eyebrow-text { line-height: 1.2; }
.plans-page .plan-clip-dot {
  width: 7px; height: 7px;
  border-radius: 50%;
  flex-shrink: 0;
}
.plans-page .plan-clip-dot--visible {
  background: #ffffff;
  box-shadow: 0 0 0 3px rgba(255, 255, 255, 0.20);
}
.plans-page .plan-clip-dot--private {
  background: rgba(255, 255, 255, 0.45);
}

/* Headline — bigger, bolder, tight leading */
.plans-page .plan-clip-name {
  margin: 0 0 12px;
  font-size: 24px;
  font-weight: 800;
  letter-spacing: -0.02em;
  line-height: 1.12;
  color: #ffffff;
  text-shadow: 0 1px 2px rgba(0, 0, 0, 0.12);
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}

/* Headline meta — drill count · total · age */
.plans-page .plan-clip-stats {
  font-size: 13px;
  font-weight: 700;
  color: rgba(255, 255, 255, 0.88);
  margin-bottom: 14px;
  font-variant-numeric: tabular-nums;
  letter-spacing: 0.01em;
}

/* Upcoming pill row */
.plans-page .plan-clip-pill-row {
  margin-bottom: 12px;
  display: flex;
  flex-wrap: wrap;
}
.plans-page .plan-clip-pill-row .plan-clip-upcoming {
  position: static;
  display: inline-flex; align-items: center; gap: 6px;
  padding: 4px 10px;
  border-radius: 999px;
  background: linear-gradient(135deg, rgba(255, 255, 255, 0.96), rgba(255, 255, 255, 0.86));
  border: 1px solid rgba(255, 255, 255, 0.6);
  color: color-mix(in srgb, var(--plans-grad-from) 85%, #0f172a);
  font-size: 11px;
  font-weight: 800;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.10);
}
.plans-page .plan-clip-pill-row .plan-clip-upcoming svg { width: 11px; height: 11px; color: color-mix(in srgb, var(--plans-grad-from) 85%, #0f172a); }

/* Drill preview list — the content anchor */
.plans-page .plan-clip-drills {
  list-style: none;
  margin: 4px 0 0;
  padding: 12px 14px;
  background: rgba(0, 0, 0, 0.16);
  border: 1px solid rgba(255, 255, 255, 0.08);
  border-radius: 12px;
  backdrop-filter: blur(2px);
  -webkit-backdrop-filter: blur(2px);
}
.plans-page .plan-clip-drill {
  display: flex; align-items: center; gap: 10px;
  padding: 6px 0;
  border-bottom: 1px solid rgba(255, 255, 255, 0.08);
  font-size: 13px;
  color: rgba(255, 255, 255, 0.95);
  line-height: 1.35;
}
.plans-page .plan-clip-drill:last-child { border-bottom: 0; }
.plans-page .plan-clip-drill-idx {
  width: 18px; height: 18px;
  border-radius: 50%;
  background: rgba(255, 255, 255, 0.92);
  color: color-mix(in srgb, var(--plans-grad-from) 80%, #0f172a);
  font-size: 10.5px;
  font-weight: 800;
  font-variant-numeric: tabular-nums;
  display: inline-flex; align-items: center; justify-content: center;
  flex-shrink: 0;
}
.plans-page .plan-clip-drill-name {
  flex: 1;
  font-weight: 600;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.plans-page .plan-clip-drill-mins {
  font-size: 11.5px;
  font-weight: 700;
  font-variant-numeric: tabular-nums;
  color: rgba(255, 255, 255, 0.7);
  letter-spacing: 0.02em;
}
.plans-page .plan-clip-drill--more {
  justify-content: center;
  padding: 8px 0 2px;
  font-size: 11.5px;
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: rgba(255, 255, 255, 0.65);
  border-bottom: 0;
}

/* Empty (no drills) state inside the card */
.plans-page .plan-clip-empty {
  padding: 14px 16px;
  background: rgba(0, 0, 0, 0.16);
  border: 1px dashed rgba(255, 255, 255, 0.20);
  border-radius: 12px;
  font-size: 13px;
  color: rgba(255, 255, 255, 0.75);
  font-weight: 500;
  text-align: center;
}

/* Hover-reveal action overlay — top right */
.plans-page .plan-clip-actions {
  position: absolute;
  top: 12px; right: 12px;
  display: flex;
  gap: 4px;
  opacity: 0;
  transform: translateY(-2px);
  transition: opacity 180ms, transform 180ms;
}
.plans-page .plan-clip:hover .plan-clip-actions,
.plans-page .plan-clip:focus-within .plan-clip-actions {
  opacity: 1;
  transform: translateY(0);
}
.plans-page .plan-clip-action {
  width: 30px; height: 30px;
  border: 0;
  border-radius: 8px;
  background: rgba(255, 255, 255, 0.95);
  color: color-mix(in srgb, var(--plans-grad-from) 75%, #0f172a);
  display: inline-flex; align-items: center; justify-content: center;
  cursor: pointer;
  transition: background 150ms, color 150ms, transform 150ms;
  box-shadow: 0 2px 6px rgba(0, 0, 0, 0.18);
}
.plans-page .plan-clip-action svg { width: 14px; height: 14px; }
.plans-page .plan-clip-action--share:hover { background: #ffffff; color: var(--plans-grad-from); transform: scale(1.06); }
.plans-page .plan-clip-action--run:hover { background: linear-gradient(135deg, #10b981, #84cc16); color: #fff; transform: scale(1.06); }
.plans-page .plan-clip-action--del:hover { background: #ef4444; color: #fff; transform: scale(1.06); }

/* The old hero/page/foot layout pieces are no longer rendered, but
   if any cached card markup escapes, hide it cleanly. */
.plans-page .plan-clip-hero,
.plans-page .plan-clip-page,
.plans-page .plan-clip-foot { display: none; }

@media (max-width: 720px) {
  .plans-page .plan-clip { padding: 18px 18px 16px; }
  .plans-page .plan-clip-name { font-size: 22px; }
}

/* ============================================================
   PLANS v5 — gradient = primary → darker primary; centered card.
   The team-set secondary is often a neutral (grey) that ruins the
   gradient, so we ignore it for the card body and derive a deeper
   shade from the primary directly.
   ============================================================ */
:root {
  /* "From" = team primary (full saturation).
     "To"   = darker, slightly desaturated version of primary, mixed
              in oklch for a perceptually-clean shadow tone. */
  --plans-grad-from: var(--brand-primary, #6c5ce7);
  --plans-grad-to:   color-mix(in oklch, var(--brand-primary, #6c5ce7) 70%, #0b0b14);
}

/* Card body now always reads as a confident primary → darker shade. */
.plans-page .plan-clip {
  background: linear-gradient(155deg, var(--plans-grad-from), var(--plans-grad-to)) !important;
  /* Centered layout for eyebrow / headline / stats / pill */
  align-items: center;
  text-align: center;
}

/* Center the inline rows */
.plans-page .plan-clip-eyebrow { justify-content: center; }
.plans-page .plan-clip-pill-row { justify-content: center; }

/* Headline + stats centered (they're block elements, so text-align
   on the parent does it, but be explicit). */
.plans-page .plan-clip-name { text-align: center; }
.plans-page .plan-clip-stats { text-align: center; }

/* Drill list — the box itself is full-width, but each row stays
   left-aligned (lists don't read well centered). */
.plans-page .plan-clip-drills,
.plans-page .plan-clip-empty {
  width: 100%;
  align-self: stretch;
  text-align: left;
}
.plans-page .plan-clip-drill { text-align: left; }
.plans-page .plan-clip-drill--more {
  text-align: center;
  justify-content: center;
}

/* Index disc on each drill row picks the darker stop (matches the
   bottom of the gradient) so the contrast against white is high. */
.plans-page .plan-clip-drill-idx {
  color: var(--plans-grad-to);
}

/* Upcoming pill text + icon use the same darker stop for legibility. */
.plans-page .plan-clip-pill-row .plan-clip-upcoming { color: var(--plans-grad-to); }
.plans-page .plan-clip-pill-row .plan-clip-upcoming svg { color: var(--plans-grad-to); }

/* Action button icon color picks the darker stop too */
.plans-page .plan-clip-action { color: var(--plans-grad-to); }
.plans-page .plan-clip-action--share:hover { color: var(--plans-grad-from); }

/* Stack badge (if it re-appears) uses darker stop too */
.plans-page .plan-clip-hero-stack { color: var(--plans-grad-to); }

/* ============================================================
   PLANS v6 — derive gradient from --panel-dark (the nav color)
   instead of --brand-primary (the swatch). The nav is the strong
   identity color most teams set deliberately for chrome; using
   it on the plan cards ties the bookshelf to the rest of the app.
   ============================================================ */
:root {
  --plans-grad-from: var(--panel-dark, var(--brand-primary, #6c5ce7));
  --plans-grad-to:   color-mix(in oklch, var(--panel-dark, var(--brand-primary, #6c5ce7)) 72%, #0b0b14);
}

/* ============================================================
   PLANS v7 — uniform card heights + 5-row drill preview.
   Reserves consistent vertical space for the drill area so a 2-drill
   plan and a 12-drill plan render at the same card height. Empty
   rows look intentional (glass panel breathing room), not broken.
   ============================================================ */

/* Cards lay out as a grid where the drill area always claims the
   remaining height. Using flex with flex: 1 on the drill list makes
   every card stretch the list to consume whatever's leftover. */
.plans-page .plans-shelf-row {
  align-items: stretch;
}
.plans-page .plan-clip {
  /* Minimum card height that holds 5 drill rows + the chrome above */
  min-height: 380px;
}

/* Drill list panel — reserve 5 rows of space; stretch to fill the
   card so the panel ends at the same baseline across the row. */
.plans-page .plan-clip-drills,
.plans-page .plan-clip-empty {
  flex: 1;
  display: flex;
  flex-direction: column;
  justify-content: flex-start;
  /* Lock 5-row minimum: row ≈ 30px (6px pad + 1.35*13px line + 6px pad) +
     panel padding 24px = ~174px. Round up to 184px so the "+ more" row
     also has room to breathe when present. */
  min-height: 184px;
}

/* When fewer than 5 drills, the panel still feels tall because we
   pad the bottom with subtle ghost dots (intentional empty state). */
.plans-page .plan-clip-drills::after {
  content: "";
  flex: 1;
  min-height: 0;
}

@media (max-width: 720px) {
  .plans-page .plan-clip { min-height: 340px; }
  .plans-page .plan-clip-drills,
  .plans-page .plan-clip-empty { min-height: 168px; }
}

/* Season footer — sits under the drill list, centered, uppercase
   eyebrow rhythm so it reads as quiet context (not a header). */
.plans-page .plan-clip-season {
  margin-top: 12px;
  text-align: center;
  font-size: 10.5px;
  font-weight: 800;
  letter-spacing: 0.10em;
  text-transform: uppercase;
  color: rgba(255, 255, 255, 0.78);
}

/* Eyebrow no longer carries season, so include the z-index pattern
   for the season footer too (kept above the gradient background). */
.plans-page .plan-clip > .plan-clip-season { position: relative; z-index: 1; }

/* Lock the headline block to always claim 2 lines of vertical space,
   regardless of whether the title is 1 line or 2.  Without this, a
   single-line title pulls the meta/stats/drills row up by ~27px and
   throws off the row baseline across the shelf. */
.plans-page .plan-clip-name {
  min-height: calc(24px * 1.12 * 2);  /* font-size × line-height × 2 lines */
  min-height: 2lh;                    /* modern browsers — same result */
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}
@media (max-width: 720px) {
  .plans-page .plan-clip-name {
    min-height: calc(22px * 1.12 * 2);
    min-height: 2lh;
  }
}

/* Use the server-computed mix target so very-dark nav colors (near-black)
   gradient toward white instead of darker (which would be invisible). */
:root {
  --plans-grad-to: color-mix(in oklch, var(--panel-dark, var(--brand-primary, #6c5ce7)) 72%, var(--plans-grad-mix-target, #0b0b14));
}

/* Vault curator button on plan cards: legacy rule parked it at top-right
   where the new hover action row lives. Move to top-left (the eyebrow is
   centered, so the corner is empty). Admin-only — non-admins never see it. */
.plans-page .plan-clip .send-to-vault-btn {
  top: 10px;
  left: 10px;
  right: auto;
  bottom: auto;
}

/* Acumin Pro Semi Condensed Bold (Adobe Fonts) — the site-wide
   display face for all headings (h1-h6), the nav, and plan card
   titles. The font-smoothing pair is critical on macOS — without it
   Chrome / Safari render condensed type with subpixel anti-aliasing
   which produces a fuzzy "not crisp" look. Adobe's specimen pages
   set the same pair. text-rendering: geometricPrecision keeps stroke
   geometry sharp at small sizes. */
h1, h2, h3, h4, h5, h6,
.plans-page .plan-clip-name,
.topnav-link,
.nav-drawer-link {
  font-family: "acumin-pro-semi-condensed", "Acumin Pro Semi Condensed",
               -apple-system, BlinkMacSystemFont, "Segoe UI",
               Geist, system-ui, sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-rendering: geometricPrecision;
}
h1, h2, h3, h4, h5, h6 { font-weight: 700; }
.plans-page .plan-clip-name { font-weight: 700; letter-spacing: -0.005em; }

/* Nav links: Bold (700) — Black (900) wasn't in the kit and was
   synthesizing into a blurry mess. Uppercase + slight tracking so
   condensed bold caps don't crash into each other. */
.topnav-link,
.nav-drawer-link {
  font-weight: 700;
  font-size: 12.5px;
  text-transform: uppercase;
  letter-spacing: 0.05em;
}
.topnav-link { padding: 8px 11px; }
.topnav-link { color: #fff; }
.topnav-link:not(.active) { color: rgba(255, 255, 255, 0.78); }

/* ─────────────────────────────────────────────────────────────
 * Account-icon dropdown — consolidates Team / Associations / Admin
 * + Sign out under the avatar so the main nav stays short. Class
 * prefix is .acct- (not .user-) on purpose: an older orphaned
 * design used .user-chip/.user-menu and the dead styles were bleeding
 * through (light-grey wrapper background). The .acct- prefix is
 * collision-free.
 * ───────────────────────────────────────────────────────────── */
.acct-chip { position: relative; display: inline-flex; }
.acct-chip-btn {
  display: inline-flex; align-items: center; justify-content: center;
  width: 34px; height: 34px;
  border: 0; padding: 0; margin-right: 6px;
  background: transparent; color: inherit;
  border-radius: 6px; cursor: pointer;
  transition: background 0.12s;
}
.acct-chip-btn:hover { background: rgba(255,255,255,0.10); }
.acct-chip.show .acct-chip-btn { background: rgba(255,255,255,0.14); }

.acct-menu {
  position: absolute; top: 100%; right: 0; margin-top: 6px;
  background: #fff; color: var(--text);
  border-radius: 8px;
  box-shadow: 0 12px 32px rgba(0,0,0,.28), 0 2px 6px rgba(0,0,0,.10);
  min-width: 220px;
  padding: 6px;
  display: none;
  z-index: 96;
}
.acct-menu.show { display: block; }
.acct-menu-item {
  display: flex; align-items: center; gap: 10px;
  width: 100%;
  padding: 9px 12px;
  border: 0; background: transparent;
  font: inherit; color: inherit; text-align: left;
  text-decoration: none; border-radius: 6px;
  cursor: pointer;
  transition: background 0.12s, color 0.12s;
}
.acct-menu-item:hover { background: var(--bg-soft, #f4f5f8); }
.acct-menu-item.active { color: var(--brand-primary); font-weight: 600; }
.acct-menu-item svg { flex: 0 0 16px; opacity: 0.7; }
.acct-menu-item:hover svg,
.acct-menu-item.active svg { opacity: 1; }
.acct-menu-divider { height: 1px; background: var(--border-soft, rgba(0,0,0,.08)); margin: 6px 0; }
.acct-menu-signout { color: #d4324a; }
.acct-menu-signout svg { color: #d4324a; opacity: 0.9; }

/* ─────────────────────────────────────────────────────────────
 * Demo mode (/demo) — drill board with no auth, no save, no team
 * features.  body.route-demo gates everything that needs login.
 * ───────────────────────────────────────────────────────────── */

/* Black brand bar above the drill board — Coachly icon + wordmark matching
   the landing page. No "demo" wording. */
.demo-banner {
  position: fixed;
  top: 0; left: 0; right: 0;
  z-index: 9000;
  display: flex; align-items: center; justify-content: space-between; gap: 16px;
  height: 48px;
  padding: 0 18px;
  background: #0c0c12;
  -webkit-font-smoothing: antialiased;
  box-shadow: 0 2px 12px rgba(0, 0, 0, 0.25);
}
.demo-brand {
  display: inline-flex; align-items: center; gap: 10px;
  text-decoration: none;
}
.demo-brand-mark {
  display: grid; place-items: center;
  width: 28px; height: 28px;
  border-radius: 7px;
  background: linear-gradient(135deg, #6c5ce7 0%, #00cec9 100%);
  color: #fff;
  font: 800 16px/1 Geist, system-ui, sans-serif;
}
.demo-brand-word {
  font-family: 'Anton', Impact, 'Arial Narrow', sans-serif;
  font-size: 21px;
  letter-spacing: 0.06em;
  color: #fff;
  line-height: 1;
}
.demo-banner-cta {
  background: linear-gradient(135deg, #6c5ce7 0%, #00cec9 100%);
  color: #fff;
  font: 700 12px/1 Geist, system-ui, sans-serif;
  letter-spacing: 0.02em;
  text-transform: uppercase;
  text-decoration: none;
  padding: 9px 14px;
  border-radius: 8px;
  transition: transform 0.12s ease, box-shadow 0.12s ease, filter 0.12s ease;
}
.demo-banner-cta:hover {
  filter: brightness(1.08);
  transform: translateY(-1px);
  box-shadow: 0 6px 16px rgba(108, 92, 231, 0.40);
}
.demo-banner-actions { display: flex; align-items: center; gap: 8px; }
.demo-banner-save {
  background: rgba(255,255,255,0.12); color: #fff; cursor: pointer;
  font: 700 12px/1 Geist, system-ui, sans-serif; letter-spacing: 0.02em; text-transform: uppercase;
  border: 1px solid rgba(255,255,255,0.25); padding: 9px 14px; border-radius: 8px;
  transition: background 0.12s ease, border-color 0.12s ease;
}
.demo-banner-save:hover { background: rgba(255,255,255,0.2); border-color: rgba(255,255,255,0.45); }

/* ── Demo email-capture popup ── */
.demo-capture-bg {
  position: fixed; inset: 0; z-index: 100000; display: none;
  align-items: center; justify-content: center; padding: 20px;
  background: rgba(10,12,18,0.55); backdrop-filter: blur(2px);
}
.demo-capture-bg.show { display: flex; }
.demo-capture {
  position: relative; width: 400px; max-width: 100%;
  background: #fff; border-radius: 16px; padding: 28px 26px 22px; text-align: center;
  box-shadow: 0 24px 60px rgba(0,0,0,0.35); animation: dcPop 0.18s ease;
}
@keyframes dcPop { from { transform: translateY(8px) scale(0.98); opacity: 0; } to { transform: none; opacity: 1; } }
.demo-capture-x {
  position: absolute; top: 12px; right: 14px; background: none; border: none;
  font-size: 22px; line-height: 1; color: var(--text-dim, #94a3b8); cursor: pointer;
}
.demo-capture-mark {
  width: 46px; height: 46px; margin: 0 auto 12px; border-radius: 12px;
  display: grid; place-items: center; color: #fff; font: 800 24px/1 Anton, Geist, sans-serif;
  background: linear-gradient(135deg, #6c5ce7 0%, #00cec9 100%);
}
.demo-capture h3 { margin: 0 0 6px; font: 700 19px/1.2 'Instrument Sans', Geist, system-ui, sans-serif; color: var(--text, #1a1d21); }
.demo-capture p { margin: 0 0 16px; font: 400 13.5px/1.5 Geist, system-ui, sans-serif; color: var(--text-dim, #64748b); }
.demo-capture-form { display: flex; flex-direction: column; gap: 9px; }
.demo-capture-form input {
  width: 100%; padding: 11px 13px; border: 1px solid var(--border, #d8dce2); border-radius: 9px;
  font: 400 15px/1.2 Geist, system-ui, sans-serif; color: var(--text); background: #fff; text-align: center;
}
.demo-capture-form input:focus { outline: 2px solid #6c5ce7; outline-offset: -1px; border-color: transparent; }
.demo-capture-form .btn-primary { padding: 11px; font-weight: 700; }
.demo-capture-err { margin-top: 10px; font: 500 12.5px/1.4 Geist, system-ui, sans-serif; color: #dc2626; }
.demo-capture-later { margin-top: 12px; background: none; border: none; cursor: pointer; font: 500 12.5px/1 Geist, system-ui, sans-serif; color: var(--text-dim, #94a3b8); text-decoration: underline; }

/* Push the app shell down so the bar doesn't cover the topbar. */
body.route-demo .app { margin-top: 48px; }
body.route-demo .topnav { display: none; }    /* topnav makes no sense without auth */

/* Hide team-only / save-bound UI in demo mode.  Everything left visible:
 * drawing tools, color, undo/redo, animation, PDF/image export, multi-tab. */
body.route-demo .sidebar,            /* drill drawer — nothing to load */
body.route-demo #expand-sidebar,     /* the strip that opens the drawer */
body.route-demo #collapse-sidebar,
body.route-demo .save-pill,          /* save indicator dot */
body.route-demo .save-dot,
body.route-demo #save-indicator,
body.route-demo .share-btn,          /* share modal trigger */
body.route-demo .btn-share,
body.route-demo .btn-push-to-teams,
body.route-demo .send-to-vault-btn,  /* curator-only */
body.route-demo .vault-revert-btn,
body.route-demo .topnav-link,        /* defensive — topnav is hidden but its children may render */
body.route-demo .acct-chip {         /* user-icon dropdown — no account */
  display: none !important;
}

/* The tab kebab menu has "Add to plan" — useless without a team's plans.
 * The whole kebab still serves Rename + Duplicate so keep it visible;
 * hide just the add-to-plan menu item. */
body.route-demo [data-tab-action="add-to-plan"] { display: none !important; }

/* Mobile drawer (hamburger) is also irrelevant in demo. */
body.route-demo .nav-hamburger,
body.route-demo .nav-drawer,
body.route-demo .nav-drawer-backdrop { display: none !important; }

/* Mobile: keep the bar single-row; shrink the CTA so it stays tappable. */
@media (max-width: 600px) {
  .demo-banner { padding: 0 12px; }
  .demo-brand-word { font-size: 18px; }
  .demo-banner-cta { padding: 8px 11px; font-size: 11px; }
}

/* ─────────────────────────────────────────────────────────────────────
 * ROSTER — lineup card (Team-Canada-prediction style, FLAT + light)
 * White surface; Forwards / Defense / Goalies sections; each player is a
 * circular headshot + a flat name pill in the team colour. Replaces the
 * grouped-table roster body.
 * ───────────────────────────────────────────────────────────────────── */
.lineup-card {
  background: transparent;       /* blends with the white table-card */
  padding: 4px 4px 18px;
  max-width: 780px;
  margin: 0 auto;
}
.lineup-head {
  display: flex; align-items: center; justify-content: center; gap: 11px;
  padding: 4px 0 16px;
}
.lineup-shield { width: 30px; height: 30px; color: var(--text, #1a1d21); flex: 0 0 30px; }
.lineup-shield svg { width: 100%; height: 100%; }
.lineup-title {
  font-family: 'acumin-pro-semi-condensed','Anton', Impact, system-ui, sans-serif;
  font-weight: 800;
  font-size: 24px;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--text, #1a1d21);
}

.lineup-section { margin-top: 18px; }
.lineup-section:first-of-type { margin-top: 4px; }
.lineup-section-head {
  text-align: center;
  font: 800 12px/1 Geist, system-ui, sans-serif;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--text-dim, #6b7280);
  margin-bottom: 12px;
}

/* Position columns (forwards = 3, defense = 2 centred). */
.lu-grid { display: grid; gap: 14px 10px; }
.lu-grid-3 { grid-template-columns: repeat(3, 1fr); }
.lu-grid-2 { grid-template-columns: repeat(2, minmax(0, 1fr)); max-width: 64%; margin: 0 auto; }
.lu-col { display: flex; flex-direction: column; gap: 14px; }
.lu-col-label {
  text-align: center;
  font: 700 10px/1 Geist, system-ui, sans-serif;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--text-dim, #9aa3af);
  margin-bottom: 2px;
}
.lu-row { display: flex; justify-content: center; gap: 18px; flex-wrap: wrap; }

/* Player tile — circular headshot above a FLAT team-colour name pill. */
.lu-tile {
  display: flex; flex-direction: column; align-items: center; gap: 8px;
  width: 100%;
  padding: 6px 4px;
  border: none; background: none; cursor: pointer;
  border-radius: 10px;
  transition: background 0.12s ease;
}
.lu-tile:hover { background: rgba(0, 0, 0, 0.035); }
.lu-avatar {
  position: relative;
  width: 56px; height: 56px; flex: 0 0 56px;
}
.lu-avatar svg, .lu-avatar img {
  width: 100%; height: 100%;
  border-radius: 50%;
  display: block;
  object-fit: cover;
  border: 2px solid #fff;
  box-shadow: 0 1px 4px rgba(0, 0, 0, 0.12);
}
/* Jersey-number badge on the headshot. */
.lu-num {
  position: absolute; bottom: -2px; right: -2px;
  min-width: 18px; height: 18px; padding: 0 4px;
  display: grid; place-items: center;
  background: var(--brand-primary, #7c5cff); color: #fff;
  border: 2px solid #fff; border-radius: 999px;
  font: 700 10px/1 'Instrument Sans', 'Geist', sans-serif;
}
/* AP (affiliate / call-up) badge — amber pill on the avatar corner. */
.lu-ap {
  position: absolute; top: -3px; left: -3px;
  height: 15px; padding: 0 4px; display: grid; place-items: center;
  background: #f59e0b; color: #fff; border: 2px solid #fff; border-radius: 999px;
  font: 800 8px/1 'Instrument Sans', 'Geist', sans-serif; letter-spacing: .04em;
}
/* AP toggle in the player edit modal. */
.ap-toggle {
  display: grid; grid-template-columns: auto 1fr; align-items: center; gap: 4px 10px;
  margin: 14px 0 4px; padding: 11px 13px; cursor: pointer;
  border: 1px solid var(--border, #e3e6ea); border-radius: 10px; background: var(--bg-soft, #f7f8fa);
}
.ap-toggle input { width: 18px; height: 18px; margin: 0; cursor: pointer; accent-color: #f59e0b; grid-row: span 2; }
.ap-toggle-text { font: 600 13px/1.2 Geist, system-ui, sans-serif; color: var(--text); }
.ap-toggle-text b { color: #b45309; }
.ap-toggle-hint { grid-column: 2; font: 500 11.5px/1.35 Geist, system-ui, sans-serif; color: var(--text-dim); }
/* Flat name pill — solid team colour, no bevel. */
.lu-name {
  width: 100%; max-width: 150px;
  text-align: center;
  padding: 6px 10px;
  border-radius: 6px;
  background: var(--brand-primary, #7c5cff);
  color: #fff;
  font: 800 12px/1.15 'acumin-pro-semi-condensed', Geist, system-ui, sans-serif;
  letter-spacing: 0.02em;
  text-transform: uppercase;
}
.lu-empty {
  text-align: center;
  color: var(--text-dim, #b6bdc7);
  font-size: 13px;
  padding: 10px 0;
}

body.route-roster #roster-groups { padding-top: 6px; }

@media (max-width: 560px) {
  .lineup-title { font-size: 20px; }
  .lu-grid-2 { max-width: 100%; }
  .lu-avatar { width: 48px; height: 48px; flex-basis: 48px; }
  .lu-name { font-size: 11px; max-width: 120px; }
}

/* ─────────────────────────────────────────────────────────────────────
 * ROSTER — drag-and-drop lineup board (lines + special teams)
 * Tabs (Lines / PP1 / PP2 / PK1 / PK2), slot grid, draggable player chips.
 * ───────────────────────────────────────────────────────────────────── */
.lu-tabs {
  display: flex; gap: 6px; justify-content: center; flex-wrap: wrap;
  padding: 2px 0 16px;
  border-bottom: 1px solid var(--border-soft);
  margin-bottom: 18px;
}
.lu-tab {
  font: 700 12px/1 'acumin-pro-semi-condensed', Geist, system-ui, sans-serif;
  letter-spacing: .06em; text-transform: uppercase;
  color: var(--text-dim);
  background: var(--bg-soft);
  border: 1px solid var(--border-soft);
  border-radius: 999px;
  padding: 8px 18px; cursor: pointer;
  transition: color .12s, border-color .12s, background .12s;
}
.lu-tab:hover { color: var(--text); border-color: var(--border); }
.lu-tab.active {
  color: #fff; border-color: transparent;
  /* Flat solid in the team primary — matches the flat name tiles. No
     gradient: a team's secondary colour can be grey/muddy and made the
     active tab fade red→grey. */
  background: var(--brand-primary, #6c5ce7);
}

.lu-board { max-width: 760px; margin: 0 auto; }
.lu-board .lineup-section-head { margin: 16px 0 10px; }
.lu-board .lineup-section-head:first-child { margin-top: 0; }

/* Line rows: [tag] + N slots in a grid. */
.lu-line { display: grid; align-items: stretch; gap: 10px; margin-bottom: 10px; }
.lu-line--f { grid-template-columns: 40px repeat(3, minmax(0, 1fr)); }
.lu-line--d { grid-template-columns: 40px repeat(2, minmax(0, 1fr)); }
.lu-line-tag {
  display: grid; place-items: center;
  font: 800 13px/1 'acumin-pro-semi-condensed', Geist, system-ui, sans-serif;
  letter-spacing: .04em; color: var(--text-dim);
}
.lu-line-head { margin-bottom: 2px; }
.lu-line-head span {
  text-align: center;
  font: 700 10px/1 Geist, system-ui, sans-serif;
  letter-spacing: .12em; text-transform: uppercase; color: var(--text-dim);
}

/* Drop-target slot. */
.lu-slot {
  min-height: 96px;
  display: flex; align-items: center; justify-content: center;
  padding: 6px;
  border: 1.5px dashed var(--border, #d4d9e0);
  border-radius: 12px;
  background: var(--bg-soft, #f6f7f9);
  transition: border-color .12s, background .12s;
}
.lu-slot.filled { border-style: solid; border-color: transparent; background: transparent; }
.lu-slot-label {
  font: 700 11px/1 Geist, system-ui, sans-serif;
  letter-spacing: .12em; text-transform: uppercase;
  color: var(--text-dim); opacity: .55;
}
.lu-drop-hover {
  border-color: var(--brand-primary, #6c5ce7) !important;
  border-style: solid !important;
  background: color-mix(in srgb, var(--brand-primary, #6c5ce7) 9%, transparent) !important;
}

/* Special-teams unit. */
.lu-unit-head { text-align: center; margin-bottom: 4px; }
.lu-unit-title {
  font: 800 19px/1.1 'acumin-pro-semi-condensed', Geist, system-ui, sans-serif;
  letter-spacing: .03em; text-transform: uppercase; color: var(--text);
}
.lu-unit-hint { font: 500 12px/1.3 Geist, system-ui, sans-serif; color: var(--text-dim); margin-top: 3px; }
.lu-unit-slots {
  display: grid; gap: 12px;
  grid-template-columns: repeat(var(--n, 3), minmax(0, 1fr));
  max-width: 540px; margin: 0 auto;
}

/* Player chip — drag handle. Reuses .lu-avatar / .lu-name visuals. */
.lu-chip {
  display: flex; flex-direction: column; align-items: center; gap: 7px;
  width: 100%;
  padding: 4px 2px;
  border-radius: 10px;
  cursor: grab;
  touch-action: none;
  -webkit-user-select: none; user-select: none;
  transition: opacity .12s;
}
.lu-chip:active { cursor: grabbing; }
.lu-chip-dragging { opacity: .32; }
.lu-dim { opacity: .26; }
.lu-ghost {
  position: fixed; z-index: 9999; margin: 0; left: 0; top: 0;
  pointer-events: none; opacity: .94;
  filter: drop-shadow(0 10px 20px rgba(0, 0, 0, .3));
}
body.lu-dragging, body.lu-dragging * { cursor: grabbing !important; }
body.lu-dragging { -webkit-user-select: none; user-select: none; }

/* Bench / available pool — wrapping drop zone. */
.lu-bench {
  display: flex; flex-wrap: wrap; gap: 14px 10px;
  min-height: 96px;
  padding: 14px;
  border: 1.5px dashed var(--border, #d4d9e0);
  border-radius: 14px;
  background: var(--bg-soft, #f6f7f9);
  align-content: flex-start;
}
.lu-bench .lu-chip { width: 92px; }
.lu-bench .lu-empty { margin: auto; font-size: 13px; }

@media (max-width: 560px) {
  .lu-line--f { grid-template-columns: 30px repeat(3, minmax(0, 1fr)); gap: 6px; }
  .lu-line--d { grid-template-columns: 30px repeat(2, minmax(0, 1fr)); gap: 6px; }
  .lu-slot { min-height: 84px; }
  .lu-unit-slots { gap: 8px; }
  .lu-bench .lu-chip { width: 78px; }
}

/* ─────────────────────────────────────────────────────────────────────
 * PUBLIC LINEUP SHARE PAGE (/lineup?t=…)
 * Read-only lineup card for a shared link. Reuses .lineup-card / .lu-* .
 * ───────────────────────────────────────────────────────────────────── */
body.route-lineup-share { background: var(--bg, #f6f7f9); }
/* Clean share surface — no app nav even if a logged-in coach previews it. */
body.route-lineup-share .topnav,
body.route-lineup-share .nav-drawer,
body.route-lineup-share .pc-ad-slot { display: none !important; }
/* Force plain block flow — the app shell styles bare <main>/grid containers
   and would otherwise collapse the share layout. */
body.route-lineup-share .lshare-page,
body.route-lineup-share .lshare-main,
body.route-lineup-share #lshare-root { display: block; width: auto; }
.lshare-page { max-width: 820px; margin: 0 auto; padding: 22px 16px 60px; box-sizing: border-box; }
.lshare-page .lineup-card { max-width: none; }
.lshare-brand { display: flex; justify-content: center; padding: 8px 0 22px; }
.lshare-brand-link { display: inline-flex; align-items: center; gap: 9px; text-decoration: none; color: var(--text, #1a1d21); }
.lshare-brand-mark { width: 26px; height: 26px; color: var(--brand-primary, #6c5ce7); }
.lshare-brand-mark svg { width: 100%; height: 100%; }
.lshare-brand-text { font: 800 18px/1 'acumin-pro-semi-condensed', Geist, system-ui, sans-serif; letter-spacing: .02em; }

.lshare-loading, .lshare-error { text-align: center; color: var(--text-dim, #6b7280); padding: 60px 20px; }
.lshare-spinner {
  width: 32px; height: 32px; margin: 0 auto 14px;
  border: 3px solid var(--border-soft, #e3e6ea);
  border-top-color: var(--brand-primary, #6c5ce7);
  border-radius: 50%; animation: lshare-spin .8s linear infinite;
}
@keyframes lshare-spin { to { transform: rotate(360deg); } }

.lshare-head { text-align: center; margin-bottom: 14px; }
.lshare-head h1 {
  font: 800 26px/1.1 'acumin-pro-semi-condensed', Geist, system-ui, sans-serif;
  letter-spacing: .03em; text-transform: uppercase; color: var(--text, #1a1d21); margin: 0;
}
.lshare-head .lshare-sub { font: 500 13px/1.3 Geist, system-ui, sans-serif; color: var(--text-dim, #6b7280); margin-top: 4px; }

.lshare-card {
  background: #fff;
  border: 1px solid var(--border-soft, #e3e6ea);
  border-radius: 16px;
  padding: 18px 18px 24px;
  box-shadow: 0 8px 30px -16px rgba(0, 0, 0, 0.2);
}
.lshare-unit-title {
  text-align: center;
  font: 800 18px/1.1 'acumin-pro-semi-condensed', Geist, system-ui, sans-serif;
  letter-spacing: .03em; text-transform: uppercase; color: var(--text, #1a1d21);
  margin: 26px 0 2px; padding-top: 18px; border-top: 1px solid var(--border-soft, #eef0f3);
}
/* The shared chips are non-interactive. */
.lu-chip--static { cursor: default; }

@media (max-width: 560px) {
  .lshare-head h1 { font-size: 21px; }
  .lshare-card { padding: 14px 12px 18px; }
}

/* ─────────────────────────────────────────────────────────────────────
 * ADMIN — Platform KPIs (/admin/kpis, operator-only)
 * Data-dense operator dashboard: hero metrics + sparklines, SVG charts,
 * engagement strip, leaderboards. Flat + brand-primary (no grey gradients).
 * ───────────────────────────────────────────────────────────────────── */
.kpi-page { max-width: 1320px; }
.kpi-page .kpi-section-label {
  font: 700 11px/1 Geist, system-ui, sans-serif;
  letter-spacing: .14em; text-transform: uppercase;
  color: var(--text-dim); margin: 26px 2px 12px;
}

/* ── Hero headline cards ── */
.kpi-hero-row {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
  gap: 14px; margin-top: 4px;
}
.kpi-hero {
  background: var(--bg, #fff); border: 1px solid var(--border, #e3e6ea);
  border-radius: 14px; padding: 16px 18px 12px; position: relative; overflow: hidden;
  box-shadow: 0 1px 2px rgba(15,30,60,0.04), 0 4px 14px rgba(15,30,60,0.04);
}
.kpi-hero-top { display: flex; align-items: center; justify-content: space-between; gap: 8px; min-height: 18px; }
.kpi-hero-label {
  font: 700 10px/1 'Instrument Sans', 'Geist', sans-serif;
  color: var(--text-dim, #6b7280); text-transform: uppercase; letter-spacing: .1em;
}
.kpi-hero-value {
  font: 600 34px/1.05 'Instrument Sans', Geist, system-ui, sans-serif;
  letter-spacing: -0.035em; color: var(--text, #1a1d21); margin: 10px 0 3px;
}
.kpi-hero-sub { font: 500 11.5px/1.35 'Instrument Sans', 'Geist', sans-serif; color: var(--text-dim, #6b7280); }
.kpi-hero-spark { margin-top: 10px; height: 28px; }
.kpi-hero-spark .pc-spark { width: 100%; height: 28px; display: block; }

/* delta pills */
.kpi-delta { font: 700 10px/1 'Instrument Sans', 'Geist', sans-serif; padding: 3px 6px; border-radius: 6px; white-space: nowrap; }
.kpi-delta--up   { color: #047857; background: rgba(16,185,129,0.12); }
.kpi-delta--down { color: #b91c1c; background: rgba(239,68,68,0.12); }
.kpi-delta--flat { color: var(--text-dim); background: var(--bg-soft, #f1f3f5); }

/* ── Chart grid ── */
.kpi-chart-grid {
  display: grid; grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 16px;
}
.chart-card {
  background: var(--bg, #fff); border: 1px solid var(--border, #e3e6ea);
  border-radius: 14px; padding: 16px 18px 14px;
  box-shadow: 0 1px 2px rgba(15,30,60,0.04), 0 4px 14px rgba(15,30,60,0.03);
}
.chart-card--wide { grid-column: 1 / -1; }
.chart-card-head { display: flex; align-items: baseline; justify-content: space-between; gap: 10px; margin-bottom: 10px; }
.chart-card-head h2 { font: 650 15px/1.2 'Instrument Sans', Geist, system-ui, sans-serif; color: var(--text); margin: 0; letter-spacing: -0.01em; }
.chart-card-meta { font: 500 10.5px/1 'Instrument Sans', 'Geist', sans-serif; color: var(--text-dim); text-transform: uppercase; letter-spacing: .06em; }
.chart-body { width: 100%; }
.chart-body .pc-svg { width: 100%; height: 210px; display: block; }
.chart-body--bars { padding-top: 2px; }
.chart-legend { display: flex; gap: 16px; margin-top: 8px; padding-left: 4px; }
.chart-legend-item { display: inline-flex; align-items: center; gap: 6px; font: 600 11px/1 Geist, system-ui, sans-serif; color: var(--text-dim); }
.chart-legend-item i { width: 10px; height: 10px; border-radius: 3px; display: inline-block; }

/* horizontal bars (drills/week, teams by sport) */
.pc-bars { display: flex; flex-direction: column; gap: 9px; padding: 4px 0 2px; }
.pc-bar-row { display: grid; grid-template-columns: 78px 1fr auto; align-items: center; gap: 10px; }
.pc-bar-label { font: 600 12px/1.2 Geist, system-ui, sans-serif; color: var(--text); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.pc-bar-track { height: 10px; border-radius: 999px; background: var(--bg-soft, #eef0f3); overflow: hidden; }
.pc-bar-fill { display: block; height: 100%; border-radius: 999px; transition: width .4s ease; }
.pc-bar-val { font: 700 12px/1 'Instrument Sans', 'Geist', sans-serif; color: var(--text); text-align: right; }
.pc-bar-val i { font: 500 10px/1 'Instrument Sans', 'Geist', sans-serif; color: var(--text-dim); font-style: normal; margin-left: 4px; }

/* donut */
.pc-donut-wrap { display: flex; align-items: center; gap: 18px; flex-wrap: wrap; }
.pc-donut { width: 150px; height: 150px; flex: 0 0 auto; }
.pc-legend { display: flex; flex-direction: column; gap: 7px; flex: 1 1 auto; min-width: 120px; }
.pc-legend-row { display: flex; align-items: center; gap: 8px; font: 600 12.5px/1 Geist, system-ui, sans-serif; color: var(--text); }
.pc-legend-row b { margin-left: auto; font: 700 12.5px/1 'Instrument Sans', 'Geist', sans-serif; }
.pc-legend-dot { width: 10px; height: 10px; border-radius: 3px; flex: 0 0 auto; }

/* chart hover tooltip */
.pc-chart-tip {
  position: fixed; z-index: 60; pointer-events: none;
  background: #1a1d21; color: #fff; border-radius: 8px; padding: 8px 10px;
  font: 500 12px/1.4 Geist, system-ui, sans-serif; box-shadow: 0 6px 22px rgba(0,0,0,0.25);
  max-width: 220px;
}
.pc-tip-h { font-weight: 700; margin-bottom: 4px; font-size: 11px; opacity: .85; }
.pc-tip-row { display: flex; align-items: center; gap: 6px; }
.pc-tip-row b { margin-left: 4px; }
.pc-tip-dot { width: 8px; height: 8px; border-radius: 2px; display: inline-block; }
.chart-body .pc-capture { cursor: crosshair; }

/* acquisition funnel (Landing → Demo → Signup) */
.kpi-funnel { display: flex; flex-direction: column; padding: 8px 0 2px; }
.kpi-funnel-stage { padding: 1px 0; }
.kpi-funnel-bar {
  background: var(--brand-primary, #7c5cff); color: #fff; border-radius: 9px;
  min-width: 60px; height: 44px; display: flex; align-items: center; padding: 0 14px;
  box-shadow: 0 1px 3px rgba(15,30,60,0.12); transition: width .45s ease;
}
.kpi-funnel-bar span { font: 700 17px/1 'Instrument Sans', Geist, system-ui, sans-serif; letter-spacing: -0.02em; }
.kpi-funnel-stage:nth-of-type(3) .kpi-funnel-bar { opacity: .84; }
.kpi-funnel-stage:nth-of-type(5) .kpi-funnel-bar { opacity: .68; }
.kpi-funnel-label {
  font: 700 10px/1 'Instrument Sans', 'Geist', sans-serif; color: var(--text-dim);
  text-transform: uppercase; letter-spacing: .08em; margin: 5px 0 2px 2px;
}
.kpi-funnel-arrow { font: 600 11px/1 Geist, system-ui, sans-serif; color: var(--text-dim); padding: 6px 0 6px 16px; }
.kpi-funnel-arrow::before { content: '↓'; margin-right: 7px; font-weight: 700; }

.kpi-label-note { font-weight: 500; letter-spacing: 0; text-transform: none; color: var(--text-dim); opacity: .8; }
.kpi-empty-note { font: 500 12.5px/1.5 Geist, system-ui, sans-serif; color: var(--text-dim); padding: 18px 4px; margin: 0; }
.kpi-empty-note code { font: 600 11.5px/1 'Instrument Sans', 'Geist', sans-serif; background: var(--bg-soft, #f1f3f5); padding: 2px 5px; border-radius: 4px; }

/* ── Self-contained stat cards (schedule/roster ones are route-scoped) ── */
.kpi-page .stats-strip {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
  gap: 14px; margin-bottom: 4px;
}
.kpi-page .stat-card {
  background: var(--bg, #fff); border: 1px solid var(--border, #e3e6ea);
  border-radius: 12px; padding: 15px 17px; position: relative; overflow: hidden;
  box-shadow: 0 1px 2px rgba(15,30,60,0.04), 0 2px 8px rgba(15,30,60,0.03);
}
.kpi-page .stat-card-label {
  font: 700 10px/1 'Instrument Sans', 'Geist', sans-serif;
  color: var(--text-dim, #6b7280); text-transform: uppercase; letter-spacing: .1em; margin-bottom: 9px;
}
.kpi-page .stat-card-value {
  font: 600 26px/1 'Instrument Sans', Geist, system-ui, sans-serif;
  letter-spacing: -0.03em; color: var(--text, #1a1d21); margin-bottom: 5px;
}
.kpi-page .stat-card-sub { font: 500 11px/1.35 'Instrument Sans', 'Geist', sans-serif; color: var(--text-dim, #6b7280); }

/* ── Tables / leaderboards ── */
.kpi-cols { display: grid; grid-template-columns: 1fr 1fr; gap: 16px; margin-top: 16px; }
.kpi-page .table-card {
  margin-top: 16px; background: var(--bg, #fff); border: 1px solid var(--border, #e3e6ea);
  border-radius: 14px; overflow: hidden;
  box-shadow: 0 1px 2px rgba(15,30,60,0.04), 0 2px 8px rgba(15,30,60,0.03);
}
.kpi-page .table-card .card-head { padding: 14px 18px 8px; }
.kpi-page .table-card .card-head h2 { font: 650 15px/1.2 'Instrument Sans', Geist, system-ui, sans-serif; color: var(--text); margin: 0; }
.kpi-table { width: 100%; border-collapse: collapse; }
.kpi-table td { padding: 9px 18px; border-top: 1px solid var(--border-soft, #eef0f3); font: 500 13px/1.3 Geist, system-ui, sans-serif; color: var(--text); }
.kpi-table tr:first-child td { border-top: none; }
.kpi-muted { color: var(--text-dim); }
.kpi-num { text-align: right; font-family: inherit; font-weight: 700; white-space: nowrap; }
td.kpi-muted.kpi-num { font-weight: 500; }

@media (max-width: 980px) { .kpi-chart-grid { grid-template-columns: 1fr; } .chart-card--wide { grid-column: auto; } }
@media (max-width: 760px) { .kpi-cols { grid-template-columns: 1fr; } }

/* ============================================================================
   PHONE DRILL BOARD  (≤640px) — bigger surface + single-row style bar
   ----------------------------------------------------------------------------
   Phones only. iPad (≥768px) keeps the wrapped style bar + its tuned layout
   from the @media (max-width:1366px) block above. Applies to the drawing app
   AND the public /demo (same view = page_drill.php).
   Ian 2026-06-24: "make the surface a lot bigger … okay if the user has to
   scroll down. the style bar is on 3 lines, looks awful. make the lines
   appear thicker on smaller screens." (line weight handled in canvas.js
   drillLineBoost()).
   ============================================================================ */
/* stylebar.js wraps each group's options in a .lp-pop and adds a .lp-trigger.
   Off phones, .lp-pop is `display: contents` (its children act as direct
   children of the group → the bar looks exactly as before) and the trigger is
   hidden. The ≤640px block below turns .lp-pop into a popover + shows the
   trigger. */
.lp-pop { display: contents; }
.lp-trigger { display: none; }

@media (max-width: 640px) {

  /* 1 — SURFACE -------------------------------------------------------------
     The rink was rendering ~168px wide inside a 390px screen: the main grid
     kept 36px side gutters AND .canvas-wrap reserved 48px-left + 86px-right
     padding (~206px wasted). Span the canvas-wrap across the full grid and
     keep only a slim left inset for the floating mode rail. */
  body.route-drill .app main > .canvas-wrap {
    grid-column: 1 / -1;
  }
  body.route-drill .canvas-wrap,
  body.route-drill.sidebar-collapsed .canvas-wrap,
  body.drill-mode-draw.route-drill .canvas-wrap {
    padding-left: 50px;     /* clears the floating mode rail (left:5px, ~40px) */
    padding-right: 6px;
    padding-bottom: 118px;  /* clears the fixed style bar + tool dock */
    /* Anchor the rink to the top instead of vertically centering it — the
       centering pushed the rink down so its bottom hid behind the fixed
       style bar. Top-anchored, the rink clears the bottom chrome. */
    justify-content: flex-start;
  }

  /* Tuck the floating DRAW/ANIM/FILE/EXPORT rail tight to the edge + compact
     it so it eats less of the surface width. */
  body.route-drill .drill-mode-switch {
    left: 5px;
    padding: 4px;
    gap: 2px;
    border-radius: 10px;
  }
  body.route-drill .drill-mode-switch .rail-section--mode button,
  body.route-drill .drill-mode-switch > button { height: 38px; }
  body.route-drill .drill-mode-switch .rail-label { font-size: 8px; }

  /* Grow the rink to fill the visible area ABOVE the fixed style bar + dock.
     Anchor it near the top (kill the desktop auto-centering slack, which
     otherwise pushes the rink down so its bottom hides behind the style
     bar) and size the stage to clear that bottom chrome (~118px). */
  body.route-drill .canvas-stage {
    min-height: calc(100vh - 214px - var(--style-bar-extra, 0px)) !important;   /* pre-dvh iOS fallback */
    max-height: none !important;
    margin-top: 6px !important;
    margin-bottom: 0 !important;
  }
  @supports (height: 100dvh) {
    body.route-drill .canvas-stage {
      min-height: calc(100dvh - 214px - var(--style-bar-extra, 0px)) !important;
    }
  }

  /* 2 — STYLE BAR -----------------------------------------------------------
     Collapse the 3-row wrap into a row of compact TRIGGER buttons; each one
     opens its options as a popover above the bar (built by stylebar.js),
     mirroring the dock's Shapes/Stamps flyouts. Only ~5 triggers, so they
     fit one row with no scroll — which lets popovers escape upward. */
  body.route-drill .line-picker {
    flex-wrap: nowrap;
    overflow: visible;            /* popovers must escape the bar upward */
    justify-content: space-around;
    align-items: stretch;
    column-gap: 4px;
    row-gap: 0;
    padding: 6px 8px;
  }
  body.route-drill .line-picker-group {
    position: relative;
    flex: 1 1 0;
    min-width: 0;
    justify-content: center;
  }
  body.route-drill .line-picker-divider { display: none; }

  /* The trigger — just the current-selection icon, centered, with a little
     dropdown arrow tucked in the bottom-right corner. */
  body.route-drill .lp-trigger {
    position: relative;
    display: flex;
    align-items: center;
    justify-content: center;
    width: 100%;
    min-height: 44px;
    padding: 6px 10px;
    border: 1px solid var(--dock-line, #e2e4e8);
    border-radius: 10px;
    background: #fff;
    color: var(--text, #1a1a1a);
    cursor: pointer;
    -webkit-appearance: none;
    appearance: none;
    touch-action: manipulation;
  }
  body.route-drill .line-picker-group.lp-open .lp-trigger {
    border-color: var(--brand-primary, #6c5ce7);
    box-shadow: 0 0 0 2px color-mix(in srgb, var(--brand-primary, #6c5ce7) 30%, transparent);
  }
  /* Flyout indicator — same corner-fold triangle the dock's flyout tools use
     (.dock-tool[data-flyout]::before): border-left transparent + border-bottom
     currentColor at 50% opacity, tucked in the bottom-right corner. */
  body.route-drill .lp-trigger::after {
    content: '';
    position: absolute;
    right: 4px;
    bottom: 4px;
    width: 0;
    height: 0;
    border-left: 4px solid transparent;
    border-bottom: 4px solid currentColor;
    opacity: 0.5;
  }
  body.route-drill .line-picker-group.lp-open .lp-trigger::after { opacity: 1; }
  body.route-drill .lp-trig-ico { display: flex; align-items: center; justify-content: center; height: 18px; }
  body.route-drill .lp-trig-ico svg,
  body.route-drill .lp-trig-ico img { width: 30px; height: 16px; object-fit: contain; }
  body.route-drill .lp-trig-dot { width: 20px; height: 20px; border-radius: 50%; border: 1px solid rgba(0,0,0,.15); }
  body.route-drill .lp-trig-num { font: 700 16px/1 Geist, system-ui, sans-serif; }

  /* The popover — hidden until the group is .lp-open. */
  body.route-drill .lp-pop { display: none; }
  body.route-drill .line-picker-group.lp-open .lp-pop {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 6px;
    position: absolute;
    bottom: calc(100% + 12px);
    left: 50%;
    transform: translateX(-50%);
    width: max-content;
    max-width: 84vw;
    padding: 10px;
    background: #fff;
    border: 1px solid var(--dock-line, #e2e4e8);
    border-radius: 14px;
    box-shadow: 0 12px 34px rgba(0,0,0,.20);
    z-index: 60;
  }
  /* The little caret pointing down at the trigger. */
  body.route-drill .line-picker-group.lp-open .lp-pop::after {
    content: '';
    position: absolute;
    top: 100%;
    left: var(--caret-x, 50%);
    transform: translateX(-50%);
    border: 7px solid transparent;
    border-top-color: #fff;
  }
  /* Inside the popover, give the option buttons / swatches comfortable taps. */
  body.route-drill .lp-pop .lp-options { flex-wrap: wrap; background: transparent; border: none; padding: 0; gap: 4px; }
  body.route-drill .lp-pop .lp-btn { min-width: 44px; min-height: 40px; padding: 4px; }
  body.route-drill .lp-pop .lp-btn svg,
  body.route-drill .lp-pop .lp-btn img { width: 30px; height: 16px; }
  body.route-drill .lp-pop .lp-btn.pos-num-btn svg { width: 30px; height: 30px; }
  body.route-drill .lp-pop .lp-swatches { gap: 8px; }
  body.route-drill .lp-pop .lp-swatches .swatch { width: 32px; height: 32px; }
  body.route-drill .lpg-size.lp-open .lp-pop { padding: 14px 16px; }
  body.route-drill .lp-pop #size-slider { width: 150px; }
  body.route-drill .lp-pop .lp-label { display: inline; font-size: 9px; }

  /* 3 — ANIMATE MODE --------------------------------------------------------
     The old phone rules left the timeline panel floating 140px off the bottom
     with the style bar overlapping it. Re-stack everything cleanly: the anim
     panel pins to the very bottom (compact, icon-only, one scrolling row),
     the style-bar triggers + tool dock sit just above it, and the rink fills
     the rest — kept as tall as the chrome allows. (Ian 2026-06-24) */
  body.drill-mode-animate.route-drill .anim-panel {
    bottom: 0;
    padding: 6px 8px 8px;
    gap: 6px;
    row-gap: 6px;
  }
  /* The nowrap scrolling toolbar inflates the flex COLUMN's cross-size to its
     ~700px min-content, so a centered width:100% child lands off-screen right.
     Pin the hint + scrubber to the viewport instead: flex-start (beat the
     panel's center alignment) + a viewport-relative width immune to the
     inflated cross-size. (Panel padding is 8px L/R → subtract 16px.) */
  body.drill-mode-animate.route-drill .anim-panel > * { min-width: 0; }
  body.drill-mode-animate.route-drill .anim-scrub,
  body.drill-mode-animate.route-drill .anim-hint {
    align-self: flex-start;
    width: calc(100vw - 16px);
  }
  /* Compact toolbar: a single horizontally-scrolling row of icon buttons. */
  body.drill-mode-animate.route-drill .anim-toolbar {
    flex-wrap: nowrap;
    overflow-x: auto;
    -webkit-overflow-scrolling: touch;
    scrollbar-width: none;
    gap: 6px;
  }
  body.drill-mode-animate.route-drill .anim-toolbar::-webkit-scrollbar { display: none; }
  body.drill-mode-animate.route-drill .anim-btn-label { display: none; }
  body.drill-mode-animate.route-drill .anim-btn { flex-shrink: 0; padding: 6px; min-width: 38px; }
  body.drill-mode-animate.route-drill .anim-timeline { margin-top: 4px; }

  /* Stack the tool dock + style bar above the pinned anim panel (no overlap,
     no dead gap). Order bottom→top: anim panel, dock, style bar, rink. */
  body.drill-mode-animate.route-drill .drill-dock  { bottom: calc(var(--anim-panel-h, 146px) + 6px) !important; }
  body.drill-mode-animate.route-drill .line-picker { bottom: calc(var(--anim-panel-h, 146px) + 60px + var(--dock-ctx-lift, 0px)) !important; }

  /* Mobile: the bottom-chrome reservation lives on the WRAP padding (see the
     unmedia'd body.drill-mode-animate.route-drill .canvas-wrap rule above — it
     applies at every width). The stage just fills the wrap. (2026-07-04 "rink
     disappears" fix.) */
  body.drill-mode-animate.route-drill .canvas-stage {
    margin: 0 !important;
    min-height: 0 !important;
    max-height: none !important;
    flex: 1 1 auto !important;
  }
}



/* ---- Rotate group in the style bar (2026-07-13) --------------------------
   Shown by canvas.js syncRotateCtx() while a rotatable stamp (net, cone,
   goal, goalie stance…) is selected with the Move tool. Own button class
   (not .lp-btn) so the style/ending handlers and the phone popover wrapper
   ignore it. Flat brand fill on press (docs/STYLE.md — no gradients). */
body.route-drill .line-picker .lpg-rotate[hidden],
body.route-drill .line-picker .lpd-rotate[hidden] { display: none; }
body.route-drill .line-picker .lpg-rotate { gap: 2px; }
body.route-drill .line-picker .lp-rot-btn {
  width: 36px; height: 30px; border: none; background: transparent; border-radius: 6px;
  color: var(--dock-text-mid, #4b5563); display: grid; place-items: center; cursor: pointer;
  transition: background 140ms ease, color 140ms ease;
}
body.route-drill .line-picker .lp-rot-btn svg { width: 18px; height: 18px; }
body.route-drill .line-picker .lp-rot-btn:hover { background: rgba(0, 0, 0, 0.06); color: var(--text); }
body.route-drill .line-picker .lp-rot-btn:active { background: var(--brand-primary); color: #fff; }
@media (max-width: 1366px) {
  /* Pencil/finger targets on tablets. */
  body.route-drill .line-picker .lp-rot-btn { width: 40px; height: 34px; }
}

/* ---- In-app help panel (2026-07-13) ---------------------------------------
   Slide-in drawer (right edge, same motion as the drills drawer) that loads
   /help in an iframe. Opened by the tabs-bar ? button, the ? key, and any
   [data-help="<post>"] link. help.js owns the behaviour. */
.help-backdrop { position: fixed; top: var(--help-panel-top, 0px); right: 0; bottom: 0; left: 0; background: rgba(15, 23, 42, 0.28); z-index: 3000; opacity: 0; transition: opacity 180ms ease; }
.help-backdrop.open { opacity: 1; }
.help-backdrop[hidden] { display: none; }
.help-panel { position: fixed; top: var(--help-panel-top, 0px); right: 0; bottom: 0; width: min(560px, 100vw); background: #fff; z-index: 3001; box-shadow: -12px 0 40px rgba(15, 23, 42, 0.18); display: flex; flex-direction: column; transform: translateX(100%); transition: transform 220ms ease; }
.help-panel.open { transform: translateX(0); }
.help-panel[hidden] { display: none; }
.help-panel-head { display: flex; align-items: center; gap: 12px; padding: 10px 12px 10px 16px; border-bottom: 1px solid #e2e4e8; font-family: Geist, system-ui, sans-serif; }
.help-panel-title { font-weight: 600; font-size: 14px; color: #171a21; flex: 1; }
.help-panel-open { font-size: 12.5px; color: #4b5263; text-decoration: none; }
.help-panel-open:hover { color: #171a21; text-decoration: underline; }
.help-panel-close { width: 32px; height: 32px; border: none; background: transparent; border-radius: 8px; font-size: 22px; line-height: 1; color: #4b5263; cursor: pointer; }
.help-panel-close:hover { background: #f1f2f4; color: #171a21; }
.help-panel-frame { flex: 1; width: 100%; border: 0; background: #fbfbfd; }
@media (prefers-reduced-motion: reduce) { .help-panel, .help-backdrop { transition: none; } }
/* Tabs-bar ? button — same chrome as the fullscreen button beside it. */
.drill-tabs-help { margin-left: 2px; }
/* Tiny ? inside the style bar's Rotate group. */
body.route-drill .line-picker .lp-rot-help { width: 22px; height: 22px; border: 1px solid var(--dock-line, #e2e4e8); background: transparent; border-radius: 50%; font: 700 11px Geist, system-ui, sans-serif; color: var(--dock-text-mid, #4b5263); cursor: pointer; display: grid; place-items: center; margin-left: 2px; }
body.route-drill .line-picker .lp-rot-help:hover { background: rgba(0, 0, 0, 0.06); color: var(--text, #171a21); }
.anim-help-link { font-weight: 600; color: #1e6fbf; text-decoration: none; }
.anim-help-link:hover { text-decoration: underline; }

/* ============================================================
   Team page — "Invite as" role picker + Who-can-do-what matrix
   (flat brand fills per docs/STYLE.md; no gradients on chrome)
   ============================================================ */
.invite-as { display: flex; flex-wrap: wrap; align-items: center; gap: 8px 12px; margin: 0 0 10px; }
.invite-as-label { font-size: 12px; font-weight: 700; letter-spacing: .06em; text-transform: uppercase; color: var(--text-dim); }
.invite-as-opts { display: inline-flex; flex-wrap: wrap; gap: 6px; }
.invite-as-opt {
  appearance: none; border: 1px solid var(--border); background: var(--panel, #fff); color: var(--text);
  padding: 6px 12px; border-radius: 999px; font-size: 13px; font-weight: 600; cursor: pointer;
  transition: background-color .15s, color .15s, border-color .15s;
}
.invite-as-opt:hover { border-color: var(--brand-primary); }
.invite-as-opt.is-on { background: var(--brand-primary); border-color: var(--brand-primary); color: #fff; }
.invite-as-blurb { flex-basis: 100%; font-size: 13px; color: var(--text-dim); }

.role-select {
  appearance: none; -webkit-appearance: none; font: inherit; font-size: 13px; font-weight: 600; color: var(--text);
  background: var(--panel, #fff) url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23666d7a' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'><path d='m6 9 6 6 6-6'/></svg>") no-repeat right 8px center / 14px;
  border: 1px solid var(--border); border-radius: 8px; padding: 5px 28px 5px 10px; cursor: pointer; max-width: 170px;
}
.role-select:focus-visible { outline: 2px solid var(--brand-primary); outline-offset: 1px; }
.role-pill { display: inline-block; padding: 3px 10px; border-radius: 999px; font-size: 12px; font-weight: 700; background: var(--bg-soft); color: var(--text); }
.role-pill.coach { background: var(--brand-primary); color: #fff; }

.access-matrix-wrap { overflow-x: auto; }
.access-table { width: 100%; border-collapse: separate; border-spacing: 0; font-size: 13px; }
.access-table th, .access-table td { padding: 9px 10px; border-bottom: 1px solid var(--border); text-align: center; white-space: nowrap; }
.access-table th:first-child, .access-table td:first-child { text-align: left; font-weight: 600; color: var(--text); }
.access-table thead th { font-size: 12px; letter-spacing: .04em; text-transform: uppercase; color: var(--text-dim); vertical-align: bottom; }
.access-table thead th .acc-role-blurb { display: block; font-size: 11px; font-weight: 400; text-transform: none; letter-spacing: 0; color: var(--text-dim); max-width: 150px; white-space: normal; margin-top: 3px; }
.acc { display: inline-block; min-width: 52px; padding: 3px 9px; border-radius: 999px; font-size: 12px; font-weight: 700; }
.acc.edit { background: var(--brand-primary); color: #fff; }
.acc.view { background: var(--bg-soft); color: var(--text); border: 1px solid var(--border); }
.acc.rsvp { background: #e3f6ea; color: #146c3a; }
.acc.none { color: var(--text-dim); font-weight: 400; }
@media (prefers-color-scheme: dark) {
  .acc.rsvp { background: rgba(31,157,85,.22); color: #8fe0b0; }
}

/* Attendance modal — RSVP request line + "replied by email" chip */
.attendance-rsvp { display: flex; flex-wrap: wrap; align-items: center; gap: 8px 12px; padding: 10px 12px; margin: 0 0 12px;
  border: 1px solid var(--border); border-radius: 10px; background: var(--bg-soft); font-size: 13px; color: var(--text); }
.attendance-rsvp .rsvp-status { flex: 1; min-width: 200px; }
.attendance-rsvp .rsvp-status b { font-weight: 700; }
.attendance-rsvp .sub { font-size: 12px; color: var(--text-dim); }
.attendance-rsvp .rsvp-help { flex-basis: 100%; font-size: 12px; color: var(--brand-primary); text-decoration: none; }
.attendance-rsvp .rsvp-help:hover { text-decoration: underline; }
.rsvp-chip { display: inline-block; margin-left: 8px; padding: 1px 8px; border-radius: 999px; font-size: 11px; font-weight: 700;
  background: #e3f6ea; color: #146c3a; vertical-align: middle; }
.rsvp-chip.sent { background: var(--bg-soft); color: var(--text-dim); border: 1px solid var(--border); }
@media (prefers-color-scheme: dark) { .rsvp-chip { background: rgba(31,157,85,.22); color: #8fe0b0; } }

/* Role-aware chrome: coach-only controls vanish for players / parents / game managers */
body:not(.role-coach):not(.role-dev_partner) .team-coach-only { display: none !important; }
body:not(.role-coach):not(.role-dev_partner) .team-profile-form input,
body:not(.role-coach):not(.role-dev_partner) .team-profile-form select { pointer-events: none; }

/* Schedule — player / parent RSVP pills + "which player is yours" banner */
.my-player-banner { display: flex; flex-wrap: wrap; align-items: center; gap: 10px 14px; padding: 14px 16px; margin: 0 0 14px;
  border: 1px solid var(--border); border-radius: 12px; background: var(--panel, #fff); font-size: 14px; color: var(--text); }
.my-player-banner b { font-weight: 700; }
.my-player-banner .sub { flex-basis: 100%; font-size: 12px; color: var(--text-dim); }
.my-player-banner select { font: inherit; font-size: 14px; padding: 7px 10px; border: 1px solid var(--border); border-radius: 8px; background: var(--panel, #fff); color: var(--text); }
.my-player-banner .btn-link { background: none; border: none; color: var(--brand-primary); font: inherit; font-size: 13px; cursor: pointer; padding: 0; text-decoration: underline; }
.rsvp-pills { display: inline-flex; gap: 4px; align-items: center; flex-wrap: nowrap; white-space: nowrap; }
.schedule-table .actions-cell .rsvp-pills { flex-direction: row; }
.schedule-table td:has(.rsvp-pills) { white-space: nowrap; }
.rsvp-pills .who { font-size: 12px; color: var(--text-dim); margin-right: 4px; }
.rsvp-pill { appearance: none; border: 1px solid var(--border); background: var(--panel, #fff); color: var(--text); font: inherit; font-size: 12px; font-weight: 600;
  padding: 4px 10px; border-radius: 999px; cursor: pointer; transition: background-color .15s, color .15s, border-color .15s; }
.rsvp-pill:hover { border-color: var(--brand-primary); }
.rsvp-pill.is-on.going { background: #1f9d55; border-color: #1f9d55; color: #fff; }
.rsvp-pill.is-on.maybe { background: var(--brand-primary); border-color: var(--brand-primary); color: #fff; }
.rsvp-pill.is-on.not_going { background: #3d4754; border-color: #3d4754; color: #fff; }
.rsvp-pills + .rsvp-pills { margin-top: 4px; }

/* ============================================================
   Importer dialog (roster / schedule CSV + .ics import)
   ============================================================ */
.importer-modal { width: 860px; max-width: 96vw; max-height: 90vh; overflow-y: auto; }
.importer-head { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 10px 20px; margin-bottom: 14px; }
.importer-head h3 { margin: 0; }
.importer-steps { list-style: none; display: flex; gap: 14px; margin: 0; padding: 0; font-size: 12px; color: var(--text-dim); }
.importer-steps li { display: flex; align-items: center; gap: 6px; }
.importer-steps li span { display: inline-grid; place-items: center; width: 20px; height: 20px; border-radius: 50%; border: 1px solid var(--border); font-size: 11px; font-weight: 700; }
.importer-steps li.on { color: var(--text); font-weight: 700; }
.importer-steps li.on span { background: var(--brand-primary); border-color: var(--brand-primary); color: #fff; }
.importer-steps li.done span { background: var(--bg-soft); color: var(--text); }
.importer-intro { font-size: 14px; color: var(--text); margin: 0 0 12px; line-height: 1.5; }
.importer-source { display: flex; flex-direction: column; gap: 10px; }
.importer-drop { display: flex; flex-direction: column; align-items: center; gap: 4px; padding: 26px 16px; border: 2px dashed var(--border); border-radius: 12px;
  text-align: center; cursor: pointer; color: var(--text); font-size: 14px; transition: border-color .15s, background-color .15s; }
.importer-drop:hover, .importer-drop.over { border-color: var(--brand-primary); background: var(--bg-soft); }
.importer-drop svg { width: 28px; height: 28px; color: var(--brand-primary); margin-bottom: 4px; }
.importer-drop .sub { font-size: 12px; color: var(--text-dim); }
.importer-or { text-align: center; font-size: 12px; color: var(--text-dim); text-transform: uppercase; letter-spacing: .08em; }
.importer-source textarea { width: 100%; font: 13px/1.4 ui-monospace, SFMono-Regular, Menlo, monospace; padding: 10px; border: 1px solid var(--border); border-radius: 8px; background: var(--panel, #fff); color: var(--text); resize: vertical; }
.importer-template { font-size: 13px; color: var(--text); background: var(--bg-soft); border-radius: 8px; padding: 10px 12px; }
.importer-template a { color: var(--brand-primary); font-weight: 600; }
.importer-error { color: #b91c1c; font-size: 13px; margin-top: 10px; }
.importer-check { display: flex; align-items: center; gap: 8px; font-size: 13px; color: var(--text); margin: 0 0 10px; }
.importer-check select { font: inherit; padding: 3px 6px; border: 1px solid var(--border); border-radius: 6px; background: var(--panel, #fff); color: var(--text); }
.importer-map-wrap, .importer-preview-wrap { overflow: auto; border: 1px solid var(--border); border-radius: 10px; }
.importer-preview-wrap { max-height: 42vh; }
.importer-map, .importer-preview { width: 100%; border-collapse: collapse; font-size: 13px; }
.importer-map th, .importer-map td, .importer-preview th, .importer-preview td { padding: 8px 10px; border-bottom: 1px solid var(--border); text-align: left; vertical-align: top; white-space: nowrap; }
.importer-map th, .importer-preview th { font-size: 11px; letter-spacing: .05em; text-transform: uppercase; color: var(--text-dim); background: var(--bg-soft); position: sticky; top: 0; }
.importer-map td .sub { font-size: 11px; color: var(--text-dim); white-space: normal; }
.importer-map .req { font-size: 10px; font-weight: 700; letter-spacing: .05em; text-transform: uppercase; color: var(--brand-primary); margin-left: 4px; }
.importer-map select { font: inherit; font-size: 13px; padding: 5px 8px; border: 1px solid var(--border); border-radius: 8px; background: var(--panel, #fff); color: var(--text); min-width: 170px; }
.importer-sample { max-width: 260px; overflow: hidden; text-overflow: ellipsis; }
.importer-summary { display: flex; flex-wrap: wrap; gap: 8px; margin: 0 0 12px; }
.importer-summary .pill { padding: 4px 10px; border-radius: 999px; font-size: 12px; font-weight: 700; }
.importer-summary .pill.ok { background: #e3f6ea; color: #146c3a; }
.importer-summary .pill.bad { background: #fde8e8; color: #9b1c1c; }
.importer-summary .pill.dup { background: var(--bg-soft); color: var(--text); border: 1px solid var(--border); }
.importer-summary .pill.warn { background: #fff4d6; color: #7a5200; }
.importer-preview tr.warn .status { color: #7a5200; }
.importer-preview tr.bad td { background: #fff5f5; }
.importer-preview tr.bad .status { color: #9b1c1c; }
.importer-preview tr.dup td { color: var(--text-dim); }
.importer-preview td.status { white-space: normal; max-width: 260px; }
.importer-done { display: flex; flex-direction: column; align-items: center; text-align: center; gap: 6px; padding: 24px 0 8px; }
.importer-done svg { width: 44px; height: 44px; padding: 8px; border-radius: 50%; background: #e3f6ea; color: #146c3a; }
.importer-done h4 { margin: 6px 0 0; font-size: 18px; }
@media (prefers-color-scheme: dark) {
  .importer-summary .pill.ok, .importer-done svg { background: rgba(31,157,85,.22); color: #8fe0b0; }
  .importer-summary .pill.bad { background: rgba(155,28,28,.25); color: #f3a2a2; }
  .importer-preview tr.bad td { background: rgba(155,28,28,.12); }
}

/* Roster modal — contact rows (Parent 1 / Parent 2 / player / other) */
.contact-rows { display: flex; flex-direction: column; gap: 6px; margin: 0 0 8px; }
.contact-row { display: grid; grid-template-columns: 104px 1fr 120px 1.4fr 28px; gap: 6px; align-items: center; }
.contact-row input, .contact-row select { width: 100%; min-width: 0; font: inherit; font-size: 13px; padding: 7px 8px; border: 1px solid var(--border); border-radius: 8px; background: var(--panel, #fff); color: var(--text); }
.contact-row .c-del { appearance: none; border: none; background: transparent; color: var(--text-dim); font-size: 18px; line-height: 1; cursor: pointer; padding: 4px; border-radius: 6px; }
.contact-row .c-del:hover { color: #b91c1c; background: var(--bg-soft); }
@media (max-width: 640px) {
  .contact-row { grid-template-columns: 1fr 1fr 28px; }
  .contact-row .c-rel { grid-column: 1; }
  .contact-row .c-name { grid-column: 2; }
  .contact-row .c-phone { grid-column: 1; }
  .contact-row .c-email { grid-column: 2; }
  .contact-row .c-del { grid-column: 3; grid-row: 1; }
}

/* Roster: only roles with edit_roster (coach, team manager) get Add / Import. */
body.route-roster:not(.role-coach):not(.role-team_manager):not(.role-dev_partner) #btn-new-player,
body.route-roster:not(.role-coach):not(.role-team_manager):not(.role-dev_partner) #btn-import-players { display: none !important; }

/* Lineup board — "Arrange by position" (lines tab, editors only) */
.lu-tabs .lu-autofill { margin-left: auto; appearance: none; border: 1px solid var(--border); background: var(--panel, #fff); color: var(--text); font: inherit; font-size: 12px; font-weight: 600; padding: 5px 10px; border-radius: 8px; cursor: pointer; }
.lu-tabs .lu-autofill:hover { border-color: var(--brand-primary); color: var(--brand-primary); }

/* Importer dialog — mobile + label overrides (the generic .modal label rule
   uppercases/letter-spaces every <label>, which wrecked the drop zone and the
   checkbox rows; and the dialog must never exceed the viewport). */
.modal.importer-modal { width: min(860px, 96vw); max-width: 96vw; box-sizing: border-box; }
.modal.importer-modal label { text-transform: none; letter-spacing: 0; font-size: 13px; font-weight: 500; margin: 0; display: flex; }
.modal.importer-modal .importer-drop { display: flex; flex-direction: column; align-items: center; font-size: 14px; font-weight: 400; margin: 0; }
.modal.importer-modal .importer-drop b { font-weight: 700; }
.modal.importer-modal .importer-check { margin: 0 0 10px; align-items: center; }
.modal.importer-modal .importer-check input[type="checkbox"] { width: 16px; height: 16px; margin: 0; flex: 0 0 auto; }
@media (max-width: 640px) {
  .modal.importer-modal { padding: 18px 14px; max-height: 94vh; }
  .importer-head { flex-direction: column; align-items: flex-start; gap: 8px; }
  .importer-steps { gap: 10px; }
  .importer-map th:nth-child(3), .importer-map td:nth-child(3) { display: none; }   /* sample values — no room */
  .importer-map select { min-width: 0; width: 100%; }
  .importer-map th, .importer-map td, .importer-preview th, .importer-preview td { padding: 7px 8px; }
  .importer-actions { flex-wrap: wrap; }
  .importer-actions .btn { flex: 1 1 auto; }
}
.importer-drop:focus-visible, .importer-modal:focus-visible { outline: 2px solid var(--brand-primary); outline-offset: 2px; }
.importer-modal:focus { outline: none; }

/* Practice plan cards — actions live in a footer row that is ALWAYS visible
   (Ian: "move these to the bottom of each practice plan and make them visible
   at all times"). Share + Delete are quiet; Run is the one solid button. */
.plans-page .plan-clip-actions {
  position: static; top: auto; right: auto;
  opacity: 1; transform: none; transition: none;
  display: flex; align-items: center; gap: 6px;
  width: 100%; align-self: stretch; box-sizing: border-box;
  margin-top: 12px; padding-top: 10px;
  border-top: 1px solid rgba(255, 255, 255, 0.28);
}
.plans-page .plan-clip-action {
  width: 34px; height: 34px; border-radius: 8px;
  background: rgba(255, 255, 255, 0.16); color: #fff; box-shadow: none;
}
.plans-page .plan-clip-action svg { width: 16px; height: 16px; }
.plans-page .plan-clip-action--share:hover { background: rgba(255, 255, 255, 0.3); color: #fff; transform: none; }
.plans-page .plan-clip-action--del:hover { background: #ef4444; color: #fff; transform: none; }
.plans-page .plan-clip-action--run {
  margin-left: auto; width: auto; padding: 0 14px 0 11px; gap: 7px;
  background: #fff; color: var(--plans-grad-from, var(--brand-primary, #7c5cff));
  font: inherit; font-size: 13px; font-weight: 700;
}
.plans-page .plan-clip-action--run svg { width: 13px; height: 13px; }
.plans-page .plan-clip-action--run:hover { background: #fff; color: var(--plans-grad-from, var(--brand-primary, #7c5cff)); transform: none; filter: brightness(0.96); }
.plans-page .plan-clip-action:focus-visible { outline: 2px solid #fff; outline-offset: 2px; }

/* Tip of the day — bottom-right bubble on the drill board (tipbubble.js) */
.tip-bubble {
  position: fixed; right: 18px; bottom: 120px; z-index: 60;
  width: 300px; max-width: calc(100vw - 36px);
  background: var(--panel, #fff); color: var(--text);
  border: 1px solid var(--border); border-radius: 12px;
  box-shadow: 0 10px 30px rgba(15, 23, 42, 0.16), 0 2px 6px rgba(15, 23, 42, 0.08);
  padding: 12px 14px 12px;
  opacity: 0; transform: translateY(10px); transition: opacity .25s ease, transform .25s ease;
}
.tip-bubble.in { opacity: 1; transform: none; }
.tip-bubble-head { display: flex; align-items: center; gap: 8px; font-size: 12px; font-weight: 700; letter-spacing: .04em; text-transform: uppercase; color: var(--brand-primary); }
.tip-bubble-head svg { width: 16px; height: 16px; }
.tip-bubble-close { appearance: none; border: none; background: transparent; margin-left: auto; width: 26px; height: 26px; border-radius: 6px; color: var(--text-dim); cursor: pointer; display: inline-grid; place-items: center; padding: 0; }
.tip-bubble-close svg { width: 13px; height: 13px; }
.tip-bubble-close:hover { background: var(--bg-soft); color: var(--text); }
.tip-bubble-text { margin: 8px 0 10px; font-size: 13.5px; line-height: 1.5; color: var(--text); }
.tip-bubble-text b { font-weight: 700; }
.tip-bubble-foot { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.tip-bubble-count { font-size: 11px; font-weight: 600; letter-spacing: 0; text-transform: none; color: var(--text-dim); margin-left: 2px; font-variant-numeric: tabular-nums; }
.tip-bubble-nav { display: inline-flex; gap: 2px; }
.tip-bubble-prev, .tip-bubble-next { appearance: none; border: 1px solid var(--border); background: var(--panel, #fff); color: var(--text); width: 28px; height: 28px; border-radius: 8px; cursor: pointer; display: inline-grid; place-items: center; padding: 0; }
.tip-bubble-prev svg, .tip-bubble-next svg { width: 14px; height: 14px; }
.tip-bubble-prev:hover, .tip-bubble-next:hover { border-color: var(--brand-primary); color: var(--brand-primary); }
.tip-bubble-off { margin-left: auto; flex-basis: 100%; text-align: right; padding-top: 2px; }
.tip-bubble-cta { appearance: none; border: none; background: var(--brand-primary); color: #fff; font: inherit; font-size: 12.5px; font-weight: 700; padding: 7px 12px; border-radius: 8px; cursor: pointer; white-space: nowrap; }
.tip-bubble-cta:hover { filter: brightness(0.94); }
.tip-bubble-off { appearance: none; border: none; background: transparent; color: var(--text-dim); font: inherit; font-size: 12px; cursor: pointer; padding: 4px 2px; }
.tip-bubble-off:hover { color: var(--text); text-decoration: underline; }
body.drill-mode-present .tip-bubble, body.pc-tour--open .tip-bubble { display: none; }
@media (max-width: 1100px) { .tip-bubble { bottom: 150px; } }
@media (prefers-reduced-motion: reduce) { .tip-bubble { transition: none; } }

/* Admin · Partners */
.partners-grid { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 10px 14px; }
.partners-grid label { display: flex; flex-direction: column; gap: 4px; font-size: 13px; font-weight: 600; color: var(--text); }
.partners-grid label .sub { font-weight: 400; font-size: 12px; }
.partners-grid label.wide { grid-column: 1 / -1; }
.partners-grid input, .partners-grid select { font: inherit; font-size: 14px; padding: 8px 10px; border: 1px solid var(--border); border-radius: 8px; background: var(--panel, #fff); color: var(--text); }
.partners-check { display: flex; align-items: center; gap: 8px; font-size: 13px; margin-top: 10px; }
.partners-table-wrap { overflow-x: auto; }
.partners-table th { white-space: nowrap; }
.partners-table td { vertical-align: top; }
.partners-table td.num { text-align: right; font-variant-numeric: tabular-nums; white-space: nowrap; }
.partners-table .sub { font-size: 12px; color: var(--text-dim); }
.pt-status { display: inline-block; padding: 2px 9px; border-radius: 999px; font-size: 12px; font-weight: 700; white-space: nowrap; }
.pt-status.on { background: #e3f6ea; color: #146c3a; }
.pt-status.mid { background: #fff4d6; color: #7a5200; }
.pt-status.wait { background: var(--bg-soft); color: var(--text); border: 1px solid var(--border); }
.pt-status.off { background: #fde8e8; color: #9b1c1c; }
.pt-spark { width: 120px; height: 26px; display: block; fill: var(--brand-primary); opacity: .85; }
.pt-actions { white-space: nowrap; }
.pt-actions .btn, .pt-actions select { font-size: 12px; padding: 4px 8px; margin: 0 2px 4px 0; }
.pt-actions select { font: inherit; font-size: 12px; border: 1px solid var(--border); border-radius: 6px; background: var(--panel, #fff); color: var(--text); }
@media (max-width: 700px) { .partners-grid { grid-template-columns: 1fr; } }

/* Split squad (MD teams) — two sides of one roster on the lineup board */
.lu-split { display: grid; grid-template-columns: 1fr 1fr; gap: 14px; margin: 6px 0 4px; }
.lu-split-col { min-width: 0; }
.lu-split-head { display: flex; align-items: baseline; justify-content: space-between; gap: 10px; margin: 0 0 6px; }
.lu-split-name { font: 700 15px/1.2 inherit; font-family: inherit; color: var(--text); background: transparent; border: 1px solid transparent; border-radius: 6px; padding: 3px 6px; min-width: 0; width: 130px; }
.lu-split-name:hover:not([readonly]) { border-color: var(--border); }
.lu-split-name:focus { border-color: var(--brand-primary); outline: none; background: var(--panel, #fff); }
.lu-split-meta { font-size: 11.5px; color: var(--text-dim); white-space: nowrap; }
.lu-bench.lu-split-side { min-height: 132px; align-content: flex-start; }
.lu-split-a { border-left: 3px solid var(--border); }
.lu-split-b { border-left: 3px solid var(--brand-primary); }
.lu-split-actions { display: flex; gap: 6px; margin-left: auto; }
@media (max-width: 700px) { .lu-split { grid-template-columns: 1fr; } }

/* Lineup share page — split squad section */
.lshare-split { display: grid; grid-template-columns: 1fr 1fr; gap: 14px; margin-top: 6px; }
.lshare-split-name { font-weight: 700; font-size: 14px; margin: 0 0 6px; color: var(--text); }
.lshare-split-list { display: flex; flex-wrap: wrap; gap: 6px; align-content: flex-start; border-left: 3px solid var(--brand-primary); padding-left: 10px; }
.lshare-split-col:first-child .lshare-split-list { border-left-color: var(--border); }
@media (max-width: 640px) { .lshare-split { grid-template-columns: 1fr; } }
@media print { .lshare-split { break-inside: avoid; } }

/* Founding Coach note on the paywall Personal card (annual cadence only) */
.pt-founders {
  font-size: 12px;
  font-weight: 600;
  color: var(--brand-primary, #c0392b);
  margin: 6px 0 2px;
  line-height: 1.35;
}
/* Association quantity picker */
.assoc-teams-label { display: inline-flex; align-items: center; gap: 8px; font-weight: 600; }
.assoc-teams-input { width: 76px; padding: 7px 9px; border: 1px solid var(--border, #d4d7dc); border-radius: 8px; font: inherit; }
.assoc-bill-total { font-weight: 700; }
.assoc-bill-total .sub { font-weight: 400; }

/* ---------- Share as image (Instagram story/post) dialog ---------- */
.share-image-card { max-width: 420px; }
.share-img-formats { display: flex; gap: 8px; margin: 14px 0 12px; }
.share-img-fmt {
  flex: 1; padding: 9px 12px; border: 1px solid var(--border, #d4d7dc);
  border-radius: 10px; background: #fff; font: inherit; font-weight: 600;
  cursor: pointer; display: flex; align-items: center; justify-content: center; gap: 8px;
}
.share-img-fmt span { font-weight: 500; font-size: 12px; color: var(--text-dim, #6e7d8b); }
.share-img-fmt.active { background: var(--brand-primary, #7c5cff); border-color: var(--brand-primary, #7c5cff); color: #fff; }
.share-img-fmt.active span { color: rgba(255,255,255,0.8); }
.share-img-preview-wrap {
  display: flex; justify-content: center; background: #f2f3f5;
  border: 1px solid var(--border, #e3e6e9); border-radius: 12px; padding: 14px; margin-bottom: 14px;
}
.share-img-preview { max-height: 46vh; max-width: 100%; border-radius: 8px; transition: opacity 150ms; }
.share-img-actions { display: flex; justify-content: flex-end; gap: 10px; }

/* Draft badge on vault cards — platform admins only ever see these */
.vault-card-draft {
  position: absolute; top: 8px; left: 8px;
  background: var(--brand-primary, #7c5cff); color: #fff;
  font-size: 10px; font-weight: 700; letter-spacing: .12em;
  padding: 3px 8px; border-radius: 6px; z-index: 2;
}

/* ---------- Public live-follow page (/game-live) ---------- */
body.route-game-live { background: var(--bg, #f7f8fa); }
.gl-page { max-width: 860px; margin: 0 auto; padding: 20px 16px 96px; } /* bottom room for the fan reaction bar */
/* Banner sides must be allowed to SHRINK — otherwise a long team name
   pushes the logo out of the row. Names ellipsize instead. */
.gl-banner .gc-side { min-width: 0; flex: 1 1 0; }
.gl-banner .gc-side-info { min-width: 0; }
.gl-banner .gc-side-name { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.gl-banner .gc-logo { flex-shrink: 0; }
/* Period summary table */
.gl-sum-table { width: 100%; border-collapse: collapse; font-size: 14px; }
.gl-sum-table th {
  text-align: center; font-size: 11px; font-weight: 700; letter-spacing: .05em;
  text-transform: uppercase; color: var(--text-dim, #6b7280);
  padding: 6px 8px; border-bottom: 1px solid var(--border-strong, #c9ced4);
}
.gl-sum-table th:first-child, .gl-sum-table td:first-child { text-align: left; }
.gl-sum-table td {
  padding: 9px 8px; text-align: center;
  border-bottom: 1px solid var(--border-soft, #e6e8eb);
  color: var(--text, #1f2227); font-variant-numeric: tabular-nums;
}
.gl-sum-table td.gl-sum-total { font-weight: 800; }
.gl-sum-team { display: inline-flex; align-items: center; gap: 8px; font-weight: 700; }
.gl-sum-sub { font-size: 10.5px; color: var(--text-dim, #6b7280); font-weight: 600; }
.gl-loading, .gl-error { text-align: center; padding: 60px 0; color: var(--text-dim, #6b7280); font-size: 15px; }
.gl-matchup {
  text-align: center; font-size: 12px; font-weight: 700;
  letter-spacing: .4px; text-transform: uppercase;
  color: var(--text-dim, #6b7280); margin-bottom: 10px;
}
.gl-banner { padding: 20px 18px; }
.gl-banner .gc-side-name { font-size: 17px; }
.gl-live-pill {
  display: inline-flex; align-items: center; gap: 6px;
  font-size: 10px; font-weight: 800; letter-spacing: .6px;
  color: var(--gl-accent, #7c5cff);
}
.gl-live-pill[hidden] { display: none; }
.gl-live-dot {
  width: 7px; height: 7px; border-radius: 50%;
  background: var(--gl-accent, #7c5cff);
  animation: gl-pulse 1.4s ease-in-out infinite;
}
@keyframes gl-pulse { 0%, 100% { opacity: 1; } 50% { opacity: .25; } }
@media (prefers-reduced-motion: reduce) { .gl-live-dot { animation: none; } }
.gl-clock { min-height: 20px; }

.gl-goal-row {
  display: flex; align-items: center; gap: 14px;
  background: #fff;
  border: 1px solid var(--border-soft, #e6e8eb);
  border-left: 3px solid var(--gl-accent, #7c5cff);
  border-radius: 10px;
  padding: 10px 14px;
  margin-bottom: 8px;
}
.gl-goal-row.opp { border-left-color: #9ca3af; }
.gl-mini-logo {
  width: 24px; height: 24px;
  border-radius: 7px;
  object-fit: cover;
  flex-shrink: 0;
}
.gl-mini-ph {
  display: flex; align-items: center; justify-content: center;
  background: var(--gl-accent, #7c5cff);
  color: #fff;
  font-size: 12px; font-weight: 800;
}
.gl-mini-opp { background: #64748b; }
.gl-goal-when {
  font-size: 11px; color: var(--text-dim, #6b7280);
  min-width: 44px; text-align: center; line-height: 1.3;
  font-variant-numeric: tabular-nums;
}
.gl-goal-when b { font-size: 12px; color: var(--text, #1f2227); }
.gl-goal-main { flex: 1; min-width: 0; }
.gl-goal-who { font-weight: 700; font-size: 14px; }
.gl-strength {
  display: inline-block; font-size: 10px; font-weight: 800;
  color: var(--gl-accent, #7c5cff);
  border: 1px solid color-mix(in srgb, var(--gl-accent, #7c5cff) 40%, transparent);
  border-radius: 999px; padding: 1px 7px; margin-left: 4px; vertical-align: 1px;
}
.gl-row-assists { font-size: 12px; color: var(--text-dim, #6b7280); margin-top: 2px; }
.gl-goal-score {
  font-weight: 800; font-size: 15px;
  font-variant-numeric: tabular-nums; color: var(--text, #1f2227);
}
/* 3D rink — GameCenter-style tilt. The rink art and the shot dots live on
   one canvas, so a single rotateX carries everything in true perspective.
   No border/box: the SVG's rounded boards float free with a drop shadow. */
.gl-shotmap-wrap {
  perspective: 950px;
  overflow: visible;
}
.gl-rink3d {
  position: relative;
  transform: rotateX(26deg);
  transform-origin: 50% 100%;
  transform-style: preserve-3d;
  margin-top: -3.5%;
}
.gl-rink3d canvas {
  display: block;
  width: 100%;
  filter: drop-shadow(0 16px 18px rgba(15, 23, 42, 0.25));
}
/* Goal pins — GameCenter-style badges. The layer shares the ice plane;
   each pin counter-rotates about its base so it stands up off the ice. */
.gl-pins {
  position: absolute;
  inset: 0;
  transform-style: preserve-3d;
  pointer-events: none;
}
.gl-pin {
  position: absolute;
  width: 34px; height: 40px;
  margin: 0; padding: 0; border: 0; background: none;
  transform: translate(-50%, -100%) rotateX(-26deg);
  transform-origin: 50% 100%;
  pointer-events: auto;
  cursor: pointer;
  filter: drop-shadow(0 3px 3px rgba(15, 23, 42, 0.35));
  transition: transform .15s;
}
.gl-pin svg { display: block; width: 100%; height: 100%; }
.gl-pin.sel {
  transform: translate(-50%, -100%) rotateX(-26deg) scale(1.22);
  filter: drop-shadow(0 4px 6px rgba(15, 23, 42, 0.45));
}
.gl-pin-shadow {
  position: absolute;
  width: 24px; height: 8px;
  border-radius: 50%;
  background: rgba(15, 23, 42, 0.28);
  filter: blur(2px);
  transform: translate(-50%, -50%);
  pointer-events: none;
}
.gl-pin-mini {
  display: inline-block;
  width: 10px; height: 12px;
  background: var(--gl-accent, #7c5cff);
  border: 1px solid #fff;
  box-shadow: 0 0 0 1px rgba(15, 23, 42, 0.2);
  border-radius: 3px 3px 6px 6px;
  margin-right: 4px;
  vertical-align: -2px;
}
.gl-shotmap-legend { display: flex; gap: 16px; flex-wrap: wrap; font-size: 12px; color: var(--text-dim, #6b7280); margin-top: 8px; }
.gl-shotmap-legend .gl-dot { display: inline-block; width: 9px; height: 9px; border-radius: 50%; margin-right: 4px; vertical-align: -1px; }
.gl-dot-us { background: rgba(124, 92, 255,.88); }
.gl-dot-opp { background: rgba(100,116,139,.8); }
.gl-dot-goal { box-shadow: 0 0 0 2px #16a34a; }
.gl-playcard {
  margin-top: 6px;
  background: #fff;
  border: 1px solid var(--border-soft, #e6e8eb);
  border-left: 3px solid #16a34a;
  border-radius: 10px;
  padding: 10px 14px;
}
.gl-playcard-head { font-weight: 800; font-size: 14px; }
.gl-playcard-sub { font-size: 12px; color: var(--text-dim, #6b7280); margin-top: 2px; }
#gl-shotmap { cursor: pointer; }
/* Event bubbles — slide in from the top, auto-dismiss. */
#gl-bubbles {
  position: fixed;
  top: 12px; left: 50%;
  transform: translateX(-50%);
  z-index: 50;
  display: flex; flex-direction: column; gap: 8px;
  width: min(420px, calc(100vw - 24px));
  pointer-events: none;
}
.gl-bubble {
  background: #1f2227;
  color: #fff;
  font-size: 14px; font-weight: 700;
  padding: 12px 16px;
  border-radius: 12px;
  border-left: 4px solid var(--gl-accent, #7c5cff);
  box-shadow: 0 10px 30px rgba(15, 23, 42, .3);
  opacity: 0;
  transform: translateY(-12px);
  transition: opacity .3s, transform .3s;
}
.gl-bubble.show { opacity: 1; transform: translateY(0); }
.gl-bubble-opp { border-left-color: #9ca3af; }
.gl-bubble-pen { border-left-color: #d97706; }
/* Parent banner on phones: ONE row — everything scales down instead of
   stacking. Overrides the coach-side gc-live-banner wrap rules. */
@media (max-width: 760px) {
  body.route-game-live .gl-banner {
    display: grid;
    grid-template-columns: 1fr auto 1fr;
    flex-wrap: nowrap;
    gap: 8px;
    padding: 12px 10px;
  }
  body.route-game-live .gl-banner .gc-divider { order: 0; flex-basis: auto; }
  /* Each side becomes a mini scoreboard block: logo + score on the line,
     name/sub full-width beneath — keeps the whole banner one visual row. */
  body.route-game-live .gl-banner .gc-side { display: grid; grid-template-columns: auto 1fr; align-items: center; gap: 3px 8px; }
  body.route-game-live .gl-banner .gc-side-us > :first-child { grid-row: 1; grid-column: 1; }
  body.route-game-live .gl-banner .gc-side-us .gc-side-score { grid-row: 1; grid-column: 2; justify-self: end; }
  body.route-game-live .gl-banner .gc-side-opp .gc-side-score { grid-row: 1; grid-column: 1; justify-self: start; }
  body.route-game-live .gl-banner .gc-side-opp > :last-child { grid-row: 1; grid-column: 2; justify-self: end; }
  body.route-game-live .gl-banner .gc-side-info { grid-row: 2; grid-column: 1 / -1; min-width: 0; }
  body.route-game-live .gl-banner .gc-side-opp .gc-side-info { text-align: right; }
  body.route-game-live .gl-banner .gc-logo { width: 30px; height: 30px; border-radius: 8px; font-size: 14px; }
  body.route-game-live .gl-banner .gc-side-name { font-size: 12px; line-height: 1.15; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
  body.route-game-live .gl-banner .gc-side-sub { font-size: 9px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
  body.route-game-live .gl-banner .gc-side-score { font-size: 26px; }
  body.route-game-live .gl-banner .gc-clock-time { font-size: 19px; padding: 0 2px; }
  body.route-game-live .gl-banner .gc-clock-period { font-size: 9px; }
  body.route-game-live .gl-banner .gl-live-pill { font-size: 9px; }
}
.gl-updated { text-align: center; font-size: 11px; color: #9ca3af; margin-top: 20px; }
.gl-brand { text-align: center; font-size: 11px; font-weight: 800; letter-spacing: .5px; color: #c3c8cf; margin-top: 6px; }
body.route-game-live .gc-section { padding: 0; margin-top: 22px; }

/* ---------- Standalone Game Center page (/game) ---------- */
/* The Game Center markup is shared with the schedule's modal shell; on the
   /game route it renders as the page itself — no backdrop, no lightbox. */
body.route-game-center .gc-page { padding-bottom: 0; }
body.route-game-center .gc-page-back { margin: 4px 0 10px; }
body.route-game-center #game-center-modal {
  position: static;
  inset: auto;
  display: block;
  background: transparent;
  backdrop-filter: none;
  -webkit-backdrop-filter: none;
  z-index: auto;
}
body.route-game-center #game-center-modal .modal {
  width: min(1160px, 100%);
  max-width: 100%;
  margin: 0 auto 40px;
  box-shadow: none;
  border: 1px solid var(--border-soft, #e6e8eb);
  max-height: none;
  overflow: visible;
}
body.route-game-center .gc-topbar { position: static; }

/* ============================================================
   EVALUATIONS — progress tracking
   ============================================================ */
.eval-team-card { padding: 16px 20px; margin-bottom: 18px; }
.eval-cat-row { display: flex; gap: 10px; flex-wrap: wrap; }
.eval-cat-card {
  flex: 1 1 120px;
  min-width: 110px;
  border: 1px solid var(--border-soft, #e6e8eb);
  border-radius: 10px;
  padding: 10px 12px;
}
.eval-cat-name { font-size: 11px; font-weight: 700; letter-spacing: .04em; text-transform: uppercase; color: var(--text-dim, #6b7280); }
.eval-cat-avg { font-size: 24px; font-weight: 800; color: var(--text, #1f2227); line-height: 1.2; font-variant-numeric: tabular-nums; }
.eval-delta { font-size: 11px; font-weight: 700; white-space: nowrap; }
.eval-delta.up { color: #16a34a; }
.eval-delta.down { color: #dc2626; }
.eval-delta.flat { color: var(--text-dim, #6b7280); }
.eval-improvers { margin-top: 12px; font-size: 13px; display: flex; gap: 14px; flex-wrap: wrap; align-items: center; }
.eval-improvers-label { font-weight: 700; font-size: 11px; letter-spacing: .04em; text-transform: uppercase; color: var(--text-dim, #6b7280); }
.eval-improver { font-weight: 600; color: var(--text, #1f2227); }
.eval-row-actions { white-space: nowrap; }
.eval-detail-row > td { background: var(--bg-soft, #f4f5f7); padding: 0 !important; }
.eval-progress-panel { padding: 14px 18px; }
.eval-legend { display: flex; gap: 12px; flex-wrap: wrap; margin-bottom: 10px; }
.eval-legend-chip {
  display: inline-flex; align-items: center; gap: 6px;
  font-size: 12px; font-weight: 600; color: var(--text, #1f2227);
  background: #fff;
  border: 1px solid var(--border-soft, #e6e8eb);
  border-radius: 999px;
  padding: 3px 10px;
}
.eval-legend-chip i { width: 9px; height: 9px; border-radius: 50%; display: inline-block; }
.eval-chart-wrap { background: #fff; border: 1px solid var(--border-soft, #e6e8eb); border-radius: 10px; padding: 8px; }
.eval-chart { display: block; }
.eval-panel-foot { margin-top: 8px; font-size: 11.5px; color: var(--text-dim, #6b7280); }
.eval-empty-note { font-size: 12.5px; color: var(--text-dim, #6b7280); }
@media (max-width: 700px) {
  .eval-table { display: block; overflow-x: auto; }
}

/* Eval development notes */
.eval-notes-block { margin-top: 12px; }
.eval-notes-head { font-size: 11px; font-weight: 700; letter-spacing: .04em; text-transform: uppercase; color: var(--text-dim, #6b7280); margin-bottom: 6px; }
.eval-note-row { display: flex; align-items: baseline; gap: 10px; padding: 5px 0; border-bottom: 1px solid var(--border-soft, #e6e8eb); font-size: 13px; }
.eval-note-date { flex-shrink: 0; width: 56px; font-size: 11px; font-weight: 700; color: var(--text-dim, #6b7280); }
.eval-note-text { flex: 1; color: var(--text, #1f2227); }
.eval-note-del { border: 0; background: none; color: var(--text-dim, #6b7280); font-size: 15px; cursor: pointer; padding: 0 4px; }
.eval-note-del:hover { color: #dc2626; }
.eval-note-add { display: flex; gap: 8px; margin-top: 10px; }
.eval-note-input { flex: 1; }
.eval-panel-foot { display: flex; align-items: center; justify-content: space-between; gap: 12px; flex-wrap: wrap; }
.eval-foot-actions { display: inline-flex; gap: 8px; }
.btn-progress { display: inline-flex; align-items: center; gap: 6px; }
.btn-progress svg { width: 13px; height: 13px; }
.btn-progress.is-open,
.btn-progress:hover { border-color: var(--brand-primary, #7c5cff); color: var(--brand-primary, #7c5cff); }

/* Player development report (/eval-report) */
.eval-report-page { max-width: 800px; margin: 0 auto; }
.eval-report-toolbar { display: flex; align-items: center; gap: 14px; flex-wrap: wrap; margin-bottom: 18px; }
.eval-report-opt { font-size: 13px; color: var(--text, #1f2227); display: inline-flex; align-items: center; gap: 6px; }
.rep-sheet { background: #fff; border: 1px solid var(--border-soft, #e6e8eb); border-radius: 12px; padding: 36px 40px; }
.rep-kicker { font-size: 11px; font-weight: 700; letter-spacing: .08em; text-transform: uppercase; color: var(--brand-primary, #7c5cff); }
.rep-name { margin: 4px 0 2px; font-size: 30px; color: var(--text, #1f2227); }
.rep-sub { font-size: 13px; color: var(--text-dim, #6b7280); }
.rep-head { border-bottom: 3px solid var(--text, #1f2227); padding-bottom: 16px; margin-bottom: 8px; }
.rep-section { margin-top: 22px; }
.rep-section h2 { font-size: 13px; font-weight: 800; letter-spacing: .05em; text-transform: uppercase; color: var(--text-dim, #6b7280); margin: 0 0 10px; }
.rep-chart-wrap { border: 1px solid var(--border-soft, #e6e8eb); border-radius: 10px; padding: 10px; }
.rep-table { width: 100%; border-collapse: collapse; font-size: 14px; }
.rep-table th { text-align: left; font-size: 11px; text-transform: uppercase; letter-spacing: .04em; color: var(--text-dim, #6b7280); padding: 6px 8px; border-bottom: 1px solid var(--border-strong, #c9ced4); }
.rep-table td { padding: 8px; border-bottom: 1px solid var(--border-soft, #e6e8eb); color: var(--text, #1f2227); }
.rep-dot { display: inline-block; width: 9px; height: 9px; border-radius: 50%; margin-right: 8px; vertical-align: 0; }
.rep-stars { color: var(--brand-primary, #7c5cff); letter-spacing: 2px; font-size: 15px; }
.rep-notes { list-style: none; margin: 0; padding: 0; }
.rep-notes li { padding: 7px 0; border-bottom: 1px solid var(--border-soft, #e6e8eb); font-size: 14px; color: var(--text, #1f2227); }
.rep-note-date { display: inline-block; min-width: 130px; font-weight: 700; font-size: 12px; color: var(--text-dim, #6b7280); }
.rep-text { font-size: 14px; line-height: 1.6; color: var(--text, #1f2227); margin: 0; }
.rep-muted { font-size: 13px; color: var(--text-dim, #6b7280); }
.rep-foot { margin-top: 28px; text-align: center; font-size: 10px; font-weight: 700; letter-spacing: .12em; text-transform: uppercase; color: var(--text-dim, #6b7280); }
@media print {
  body.route-eval-report .topnav,
  body.route-eval-report .no-print { display: none !important; }
  body.route-eval-report { background: #fff !important; }
  body.route-eval-report .page { padding: 0 !important; max-width: none; }
  .rep-sheet { border: 0; border-radius: 0; padding: 0; }
}

.eval-group-label, .eval-cat-group-title {
  font-size: 11px; font-weight: 800; letter-spacing: .05em; text-transform: uppercase;
  color: var(--text-dim, #6b7280);
  margin: 14px 0 8px;
}
.eval-table-heading {
  font-size: 12px; font-weight: 800; letter-spacing: .05em; text-transform: uppercase;
  color: var(--text-dim, #6b7280);
  padding: 14px 0 6px;
}
.eval-table + .eval-table-heading { margin-top: 10px; border-top: 1px solid var(--border-soft, #e6e8eb); padding-top: 16px; }

/* Player profile page */
.pp-jersey {
  width: 56px; height: 56px;
  display: flex; align-items: center; justify-content: center;
  background: var(--brand-primary, #7c5cff);
  color: #fff;
  font-size: 24px; font-weight: 800;
  border-radius: 14px;
  font-variant-numeric: tabular-nums;
}
.pp-inactive { font-size: 12px; font-weight: 700; color: var(--text-dim, #6b7280); vertical-align: middle; }
.pp-ranks { display: flex; gap: 10px; flex-wrap: wrap; }
.pp-rank {
  font-size: 13px; color: var(--text, #1f2227);
  border: 1px solid var(--border-soft, #e6e8eb);
  border-radius: 999px;
  padding: 5px 13px;
}
.pp-rank b { color: var(--brand-primary, #7c5cff); }
.pp-rank-val { color: var(--text-dim, #6b7280); font-size: 12px; }
.pp-rank-eval { background: var(--bg-soft, #f4f5f7); }
.pp-log-row { cursor: pointer; }
.pp-log-row:hover td { background: color-mix(in srgb, var(--brand-primary, #7c5cff) 4%, #fff); }
.pp-opp { font-weight: 600; }
.pp-res { font-weight: 800; font-size: 12px; margin-right: 5px; }
.pp-res-win { color: #16a34a; }
.pp-res-loss { color: #dc2626; }
.pp-res-tie { color: var(--text-dim, #6b7280); }
.pp-score { font-variant-numeric: tabular-nums; color: var(--text-dim, #6b7280); }
.pp-ratings { display: flex; gap: 10px 18px; flex-wrap: wrap; }
.pp-rating { font-size: 13.5px; color: var(--text, #1f2227); }
.pp-rating b { margin-left: 2px; }
@media (max-width: 700px) {
  .player-page .pp-log { display: block; overflow-x: auto; }
}

/* Player profile — broadcast layout */
.player-page { max-width: 900px; margin: 0 auto; }
.pp-hero { text-align: center; padding: 26px 0 4px; }
.pp-hero-row { display: flex; align-items: center; justify-content: center; gap: 26px; margin-bottom: 12px; }
.pp-hero-logo { width: 54px; height: 54px; border-radius: 12px; object-fit: cover; }
.pp-hero-logo-ph {
  display: flex; align-items: center; justify-content: center;
  background: var(--bg-soft, #f4f5f7); border: 1px solid var(--border-soft, #e6e8eb);
  color: var(--text-dim, #6b7280); font-weight: 800; font-size: 22px;
}
.pp-hero-avatar {
  width: 86px; height: 86px; border-radius: 50%;
  display: flex; align-items: center; justify-content: center;
  background: var(--brand-primary, #7c5cff); color: #fff;
  font-size: 34px; font-weight: 800; font-variant-numeric: tabular-nums;
  border: 3px solid #fff;
  box-shadow: 0 0 0 2px var(--border-strong, #c9ced4);
}
.pp-hero-num { font-size: 30px; font-weight: 300; color: var(--text, #1f2227); min-width: 54px; text-align: left; }
.pp-badge-inactive {
  display: block; font-size: 9px; font-weight: 800; letter-spacing: .08em;
  background: var(--text-dim, #6b7280); color: #fff; border-radius: 4px; padding: 2px 6px; margin-top: 4px;
}
.pp-hero-name {
  margin: 0; font-size: 32px; font-weight: 500; color: var(--text, #1f2227);
  padding-bottom: 12px; border-bottom: 1px solid var(--border-strong, #c9ced4);
  max-width: 520px; margin: 0 auto;
}
.pp-hero-sub { font-size: 13px; color: var(--text-dim, #6b7280); margin-top: 10px; }

.pp-sec-title {
  display: flex; align-items: center; gap: 8px;
  font-size: 15px; font-weight: 800; letter-spacing: .04em; text-transform: uppercase;
  color: var(--text, #1f2227);
  margin: 28px 0 10px;
}
.pp-sec-title i { width: 4px; height: 18px; background: var(--brand-primary, #7c5cff); border-radius: 1px; }

.pp-stats-card { padding: 18px 16px 12px; }
.pp-donut-row { display: grid; grid-template-columns: repeat(auto-fit, minmax(110px, 1fr)); gap: 10px; }
.pp-donut { text-align: center; }
.pp-donut-label { font-size: 10.5px; font-weight: 700; letter-spacing: .05em; text-transform: uppercase; color: var(--text-dim, #6b7280); margin-bottom: 4px; }
.pp-donut-svg { width: 96px; height: 96px; }
.pp-donut-val { font-size: 17px; font-weight: 800; fill: var(--text, #1f2227); }
.pp-donut-leader { font-size: 9px; font-weight: 600; fill: var(--text-dim, #9aa3ad); }
.pp-donut-legend { margin-top: 8px; font-size: 11.5px; color: var(--text-dim, #6b7280); display: flex; align-items: center; justify-content: center; gap: 6px; }
.pp-donut-legend i { display: inline-block; width: 9px; height: 9px; border-radius: 50%; }
.pp-leg-player { background: var(--brand-primary, #7c5cff); }
.pp-leg-leader { background: var(--border-soft, #e6e8eb); margin-left: 10px; }

.pp-info-card { padding: 4px 20px; }
.pp-info-line { display: grid; grid-template-columns: 1fr 1fr; gap: 24px; border-bottom: 1px solid var(--border-soft, #e6e8eb); }
.pp-info-line:last-child { border-bottom: 0; }
.pp-info-cell { padding: 11px 0; }
.pp-info-label { font-size: 10.5px; font-weight: 700; letter-spacing: .06em; text-transform: uppercase; color: var(--text-dim, #6b7280); }
.pp-info-val { font-size: 15px; color: var(--text, #1f2227); margin-top: 2px; }

.pp-eval-card, .pp-notes-card { padding: 16px 20px; }
.pp-eval-actions { display: flex; gap: 10px; margin-top: 12px; flex-wrap: wrap; }
.pp-log-card .pp-log { width: 100%; }
@media (max-width: 700px) {
  .pp-hero-row { gap: 14px; }
  .pp-hero-avatar { width: 68px; height: 68px; font-size: 26px; }
  .pp-hero-num { font-size: 22px; }
  .pp-log-card { overflow-x: auto; }
  .pp-log-card .pp-log { min-width: 560px; }
}

.eval-player-link { color: var(--text, #1f2227); text-decoration: none; }
.eval-player-link:hover b { color: var(--brand-primary, #7c5cff); text-decoration: underline; }
.lu-chip .lu-name:hover { text-decoration: underline; }

.pp-toolbar { display: flex; align-items: center; justify-content: space-between; gap: 12px; padding-top: 14px; }
.pp-switch { display: flex; align-items: center; gap: 6px; flex-wrap: wrap; max-width: 100%; }
/* Phones: the switcher + Compare select were poking past the viewport and
 * dragging the whole profile page sideways (Ian 2026-09-01). Wrap the
 * toolbar, cap the selects, and let wide tables scroll inside their card. */
@media (max-width: 640px) {
  .pp-switch { justify-content: center; row-gap: 8px; }
  .pp-switch select { max-width: 44vw; }
  body.route-player .card { overflow-x: auto; -webkit-overflow-scrolling: touch; }
  /* The game log lives in a .table-card, not a .card — scroll it there. */
  body.route-player .table-card { overflow-x: auto; -webkit-overflow-scrolling: touch; }
}
.pp-switch select {
  font-size: 13px; font-weight: 600;
  padding: 5px 10px;
  border: 1px solid var(--border, #d5d9dd);
  border-radius: var(--r, 8px);
  background: #fff; color: var(--text, #1f2227);
  max-width: 220px;
}
.pp-switch-arrow { display: inline-flex; align-items: center; justify-content: center; padding: 5px 7px; }
.pp-switch-arrow svg { width: 14px; height: 14px; }
.pp-notes-card .eval-note-add { margin-top: 12px; }
@media (max-width: 700px) {
  .pp-switch select { max-width: 150px; }
}

/* Plan chip on the schedule is a real button; parents get a read-only peek */
button.schedule-plan-chip { cursor: pointer; font-family: inherit; }
button.schedule-plan-chip:hover { text-decoration: none; filter: brightness(1.22); }
.plan-peek-list { margin: 0 0 4px; padding-left: 22px; }
.plan-peek-list li { display: flex; align-items: baseline; gap: 10px; padding: 6px 0; border-bottom: 1px solid var(--border-soft, #e6e8eb); font-size: 14px; }
.plan-peek-list li::marker { color: var(--text-dim, #6b7280); font-size: 12px; }
.plan-peek-name { flex: 1; font-weight: 600; color: var(--text, #1f2227); }
.plan-peek-mins { font-size: 12px; color: var(--text-dim, #6b7280); font-variant-numeric: tabular-nums; }
.plan-peek-notes { margin-top: 10px; font-size: 13px; color: var(--text, #1f2227); background: var(--bg-soft, #f4f5f7); border-radius: 8px; padding: 10px 12px; white-space: pre-wrap; }

/* Parent "My player" overview cards on the schedule */
.my-player-cards { display: flex; align-items: center; gap: 14px; flex-wrap: wrap; padding: 12px 16px; }
.my-player-card {
  display: flex; align-items: center; gap: 12px;
  border: 1px solid var(--border-soft, #e6e8eb);
  border-radius: 12px;
  padding: 10px 14px;
  background: #fff;
}
.my-player-jersey {
  width: 42px; height: 42px;
  display: flex; align-items: center; justify-content: center;
  background: var(--brand-primary, #7c5cff); color: #fff;
  font-weight: 800; font-size: 17px;
  border-radius: 11px;
  font-variant-numeric: tabular-nums;
}
.my-player-name { font-weight: 700; font-size: 14.5px; color: var(--text, #1f2227); }
.my-player-line { font-size: 12px; color: var(--text-dim, #6b7280); font-variant-numeric: tabular-nums; }

.pt-alt-email { color: var(--brand-primary, #7c5cff); font-weight: 600; }

/* Parent/player dashboard: overview only — coaching tools hide */
body.dash-fan #dashboard-ai-card,
body.dash-fan #dashboard-ai-loading,
body.dash-fan #dashboard-ai-error,
body.dash-fan #dashboard-results,
body.dash-fan #dash-widget-recent,
body.dash-fan #dash-widget-fav { display: none !important; }
body.dash-fan .dash-widgets { grid-template-columns: 1fr; }
body.dash-fan .dashboard-hero { padding-bottom: 8px; }
.dash-my-players { margin: 14px 0 4px; padding: 0; }

/* Read-only Game Center for parents & players */
body.gc-fan #gc-clock-toggle,
body.gc-fan #gc-clock-reset,
body.gc-fan #shot-period-len,
body.gc-fan .shot-mode-toggle,
body.gc-fan .shot-attack-group,
body.gc-fan #shot-flip-period,
body.gc-fan #shot-lock-period,
body.gc-fan #shot-goalie-select,
body.gc-fan .gc-strip-divider,
body.gc-fan #gc-undo-shot,
body.gc-fan #gc-add-penalty,
body.gc-fan .gc-fo-group,
body.gc-fan #gc-live-link,
body.gc-fan #gc-share { display: none !important; }
body.gc-fan #gc-clock-time { cursor: default; }
body.gc-fan #shot-rink-stage { cursor: default; }

/* Up Next rows: location line + directions pin */
.dash-upnext-row { padding: 0; }
.dash-upnext-main {
  flex: 1; min-width: 0;
  display: flex; align-items: center; gap: 12px;
  padding: 8px 8px;
  text-decoration: none; color: var(--text, #1f2227);
  border-radius: 8px;
}
.dash-upnext-text { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 1px; }
.dash-upnext-loc { font-size: 11.5px; color: var(--text-dim, #6b7280); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.dash-upnext-dir {
  flex-shrink: 0;
  display: inline-flex; align-items: center; justify-content: center;
  width: 32px; height: 32px; margin-right: 6px;
  border: 1px solid var(--border-soft, #e6e8eb);
  border-radius: 8px;
  color: var(--text-dim, #6b7280);
}
.dash-upnext-dir:hover { color: var(--brand-primary, #7c5cff); border-color: var(--brand-primary, #7c5cff); }
.dash-upnext-dir svg { width: 15px; height: 15px; }
/* Calendar month indicator */
.dash-cal { position: relative; }
.dash-cal-month {
  position: absolute; top: 8px; left: 10px;
  font-size: 11px; font-weight: 800; letter-spacing: .06em; text-transform: uppercase;
  color: var(--text-dim, #6b7280);
}
.dash-cal-tip-loc { display: block; font-size: 10.5px; color: var(--text-dim, #9aa3ad); font-weight: 500; }

.venue-dir {
  font-size: 11px; font-weight: 700;
  color: var(--brand-primary, #7c5cff);
  text-decoration: none;
  margin-left: 6px;
}
.venue-dir:hover { text-decoration: underline; }

/* Parent dashboard: shared practice plans */
.dash-shared-plans { padding: 14px 18px; margin: 14px 0 4px; }
.dash-shared-title { font-size: 11px; font-weight: 800; letter-spacing: .05em; text-transform: uppercase; color: var(--text-dim, #6b7280); margin-bottom: 8px; }
.dash-shared-plan {
  display: flex; align-items: baseline; justify-content: space-between; gap: 14px;
  width: 100%;
  background: none; border: 0; border-bottom: 1px solid var(--border-soft, #e6e8eb);
  padding: 9px 2px; cursor: pointer; text-align: left;
  font: inherit; color: var(--text, #1f2227);
}
.dash-shared-plan:last-child { border-bottom: 0; }
.dash-shared-plan:hover .dash-shared-plan-name { color: var(--brand-primary, #7c5cff); }
.dash-shared-plan-name { font-weight: 700; font-size: 14px; }
.dash-shared-plan-meta { font-size: 12px; color: var(--text-dim, #6b7280); white-space: nowrap; }

/* Attach-plan modal: occupied practices are unmistakable */
.attach-practice-current--this { color: #16a34a; font-weight: 700; }
.attach-practice-current--other { color: #b45309; }
.attach-practice-item.has-other-plan { background: #fffaf0; border-color: #fcd9a4; }

/* Player profile: streak chips + season shot map */
.pp-streak-row { display: flex; gap: 8px; flex-wrap: wrap; margin-bottom: 12px; }
.pp-streak {
  font-size: 12px; font-weight: 700;
  color: var(--brand-primary, #7c5cff);
  background: color-mix(in srgb, var(--brand-primary, #7c5cff) 8%, #fff);
  border: 1px solid color-mix(in srgb, var(--brand-primary, #7c5cff) 30%, #fff);
  border-radius: 999px;
  padding: 4px 12px;
}
.pp-map-card { padding: 14px 16px; }
.pp-map-wrap canvas { display: block; }
.pp-map-legend { display: flex; gap: 16px; font-size: 12px; color: var(--text-dim, #6b7280); margin-top: 8px; }
.pp-map-dot { display: inline-block; width: 10px; height: 10px; border-radius: 50%; margin-right: 4px; vertical-align: -1px; }
.pp-map-dot--goal { background: var(--brand-primary, #7c5cff); box-shadow: 0 0 0 1.5px #fff, 0 0 0 2.5px var(--border-strong, #c9ced4); }
.pp-map-dot--shot { background: rgba(100,116,139,0.45); }

/* Game Center: shooting zones */
.gc-zone-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 20px; }
@media (max-width: 700px) { .gc-zone-grid { grid-template-columns: 1fr; } }
.gc-zone-team { font-size: 12px; font-weight: 800; color: var(--text, #1f2227); margin-bottom: 6px; }
.gc-zone-table { width: 100%; border-collapse: collapse; font-size: 13px; }
.gc-zone-table th { text-align: left; font-size: 10.5px; text-transform: uppercase; letter-spacing: .04em; color: var(--text-dim, #6b7280); padding: 4px 8px; border-bottom: 1px solid var(--border-strong, #c9ced4); }
.gc-zone-table td { padding: 6px 8px; border-bottom: 1px solid var(--border-soft, #e6e8eb); color: var(--text, #1f2227); font-variant-numeric: tabular-nums; }
.gc-zone-table th:not(:first-child), .gc-zone-table td:not(:first-child) { text-align: center; width: 52px; }
.gc-zone-note { margin-top: 8px; font-size: 11px; color: var(--text-dim, #6b7280); }

.pp-map-toolbar { margin-bottom: 10px; }
.pp-map-toolbar select {
  font-size: 13px; font-weight: 600;
  padding: 5px 10px;
  border: 1px solid var(--border, #d5d9dd);
  border-radius: 8px;
  background: #fff; color: var(--text, #1f2227);
}
.pp-map-zones { margin-left: auto; font-weight: 700; color: var(--text, #1f2227); font-variant-numeric: tabular-nums; }

/* Live tab: per-period shooter chips */
.gc-shooters {
  display: flex; align-items: center; gap: 8px; flex-wrap: wrap;
  padding: 8px 2px 0;
}
.gc-shooters-label {
  font-size: 10.5px; font-weight: 800; letter-spacing: .05em; text-transform: uppercase;
  color: var(--text-dim, #6b7280);
  margin-right: 2px;
}
.gc-shooter-chip {
  font-size: 12px; font-weight: 600;
  color: var(--text, #1f2227);
  border: 1px solid var(--border-soft, #e6e8eb);
  border-radius: 999px;
  padding: 3px 10px;
  background: #fff;
}
.gc-shooter-chip b { font-weight: 800; }
.gc-shooter-chip i {
  font-style: normal; font-weight: 800;
  color: var(--brand-primary, #7c5cff);
  margin-left: 4px;
}
.gc-shooter-chip.has-goal { border-color: color-mix(in srgb, var(--brand-primary, #7c5cff) 45%, #fff); }

.gc-shooter-chip { cursor: pointer; font-family: inherit; transition: border-color .12s, background .12s; }
.gc-shooter-chip.is-active {
  background: var(--brand-primary, #7c5cff);
  border-color: var(--brand-primary, #7c5cff);
  color: #fff;
}
.gc-shooter-chip.is-active i { color: #fff; }

.season-map-wrap canvas { display: block; }
#season-map-card .pp-map-legend { margin-top: 8px; }

/* Goalie net map */
.pp-net-card { padding: 14px 16px; }
.pp-net-wrap { display: flex; justify-content: center; }
.pp-net-wrap canvas { display: block; }
.pp-net-tally { text-align: center; margin-top: 10px; font-size: 13px; font-weight: 700; color: var(--text, #1f2227); }

/* Game Center coach notes */
.gc-notes-input {
  width: 100%;
  font: inherit; font-size: 14px;
  padding: 10px 12px;
  border: 1px solid var(--border, #d5d9dd);
  border-radius: 10px;
  resize: vertical;
  color: var(--text, #1f2227);
}
.gc-notes-foot { display: flex; align-items: center; justify-content: flex-end; gap: 10px; margin-top: 8px; }
.gc-notes-status { font-size: 12px; font-weight: 700; color: #16a34a; }

/* Player comparison */
#pp-compare-select {
  font-size: 13px; font-weight: 600;
  padding: 5px 10px; margin-left: 6px;
  border: 1px solid var(--border, #d5d9dd);
  border-radius: var(--r, 8px);
  background: #fff; color: var(--text, #1f2227);
  max-width: 170px;
}
.ppc-card { padding: 22px 24px; }
.ppc-heads { display: flex; align-items: center; justify-content: space-around; gap: 10px; margin-bottom: 18px; }
.ppc-head { text-align: center; }
.ppc-avatar { margin: 0 auto 8px; width: 64px; height: 64px; font-size: 24px; }
.ppc-name { font-weight: 800; font-size: 16px; color: var(--text, #1f2227); }
.ppc-sub { font-size: 12px; color: var(--text-dim, #6b7280); }
.ppc-vs { font-size: 13px; font-weight: 800; letter-spacing: .1em; color: var(--text-dim, #6b7280); }
.ppc-table { width: 100%; border-collapse: collapse; }
.ppc-table td { padding: 10px 8px; border-bottom: 1px solid var(--border-soft, #e6e8eb); font-variant-numeric: tabular-nums; }
.ppc-table tr:last-child td { border-bottom: 0; }
.ppc-metric { text-align: center; font-size: 11px; font-weight: 700; letter-spacing: .05em; text-transform: uppercase; color: var(--text-dim, #6b7280); width: 34%; }
.ppc-val { text-align: center; font-size: 17px; font-weight: 600; color: var(--text, #1f2227); width: 33%; }
.ppc-val.ppc-win { font-weight: 800; color: var(--brand-primary, #7c5cff); }

/* Penalty outcome badges (inferred from the clock window) */
.gc-pen-outcome { font-size: 11px; font-weight: 800; white-space: nowrap; margin-left: auto; }
.gc-pen-outcome.good { color: #16a34a; }
.gc-pen-outcome.bad { color: #dc2626; }
.gc-pen-outcome.dim { color: var(--text-dim, #6b7280); }

.pp-trend-card { padding: 14px 16px; }
.pp-trend-wrap canvas { display: block; }

.btn-vs.is-armed { background: var(--brand-primary, #7c5cff); border-color: var(--brand-primary, #7c5cff); color: #fff; }

/* Parent live page goalie line */
.gl-goalie-line { display: flex; align-items: center; gap: 8px; margin-top: 10px; font-size: 13px; color: var(--text, #1f2227); }
/* Schedule: last-meeting scouting chip */
.last-meeting { font-size: 11.5px; color: var(--text-dim, #6b7280); }
.last-meeting b { font-variant-numeric: tabular-nums; }
.last-meeting .lm-w { color: #16a34a; }
.last-meeting .lm-l { color: #dc2626; }
.last-meeting .lm-t { color: var(--text-dim, #6b7280); }

.cal-entry-loc { display: block; font-size: 10.5px; font-weight: 500; color: var(--text-dim, #6b7280); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

.opp-table td, .opp-table th { font-variant-numeric: tabular-nums; }
.opp-good { color: #16a34a; font-weight: 700; }
.opp-bad { color: #dc2626; font-weight: 700; }
@media (max-width: 700px) { #opponent-card { overflow-x: auto; } .opp-table { min-width: 560px; } }

.splits-head { display: flex; align-items: center; justify-content: space-between; flex-wrap: wrap; gap: 10px; }
.splits-controls { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }

.sq-headline { display: flex; gap: 28px; flex-wrap: wrap; padding: 4px 0 14px; border-bottom: 1px solid rgba(15,23,42,0.08); margin-bottom: 12px; }
.sq-stat-label { font-size: 11px; font-weight: 700; text-transform: uppercase; letter-spacing: 0.04em; color: #5b6572; }
.sq-stat-val { font-size: 26px; font-weight: 800; color: #0f172a; font-variant-numeric: tabular-nums; }
.sq-up { color: #16a34a; }
.sq-down { color: #dc2626; }
.sq-grade { display: inline-block; min-width: 26px; text-align: center; font-weight: 800; font-size: 12px; padding: 2px 5px; border-radius: 5px; color: #fff; margin-right: 8px; }
.sq-ap { background: #dc2626; }
.sq-a { background: #ea580c; }
.sq-b { background: #d97706; }
.sq-c { background: #64748b; }
.sq-desc { color: #475569; font-size: 12px; }
.sq-dim { color: #5b6572; }
.sq-table td, .sq-table th { font-variant-numeric: tabular-nums; }
.sq-share { display: inline-block; vertical-align: middle; width: 64px; height: 6px; background: rgba(15,23,42,0.08); border-radius: 3px; overflow: hidden; margin-right: 6px; }
.sq-share i { display: block; height: 100%; background: var(--brand-primary); border-radius: 3px; }
.sq-share-n { font-size: 12px; color: #475569; }
.sq-periods { padding: 2px 0 6px; font-size: 14px; color: #1e293b; }
.sq-foot { margin-top: 12px; padding-top: 10px; border-top: 1px solid rgba(15,23,42,0.08); font-size: 12px; color: #475569; }
.sq-sub { margin-top: 14px; }
.pp-trend-legend { margin-top: 8px; font-size: 12px; color: #475569; display: flex; align-items: center; gap: 6px; }
.pp-trend-legend .tl-solid, .pp-trend-legend .tl-dash { display: inline-block; width: 20px; height: 0; border-top: 3px solid var(--brand-primary); }
.pp-trend-legend .tl-dash { border-top: 2px dashed rgba(15,23,42,0.45); margin-left: 10px; }
@media (max-width: 700px) { .sq-headline { gap: 18px; } .sq-stat-val { font-size: 22px; } }

.eval-note-add textarea { flex: 1; resize: vertical; min-height: 64px; font: inherit; padding: 10px 12px; border: 1px solid rgba(15,23,42,0.18); border-radius: 8px; }
.eval-note-add { align-items: flex-start; }
.eval-note-add textarea:focus { outline: 2px solid var(--brand-primary); outline-offset: 1px; }

tr.row-openable { cursor: pointer; }
tr.row-openable:hover td { background: rgba(15,23,42,0.03); }
.gc-xg-chip { font-size: 11px; font-weight: 700; color: #475569; margin-left: 8px; text-transform: none; letter-spacing: 0; }
.gc-net-grid { display: flex; gap: 24px; flex-wrap: wrap; }
.gc-net-panel { flex: 1 1 240px; min-width: 220px; }
.gc-net-wrap { margin-top: 8px; }
.gc-net-tally { margin-top: 6px; font-size: 12px; color: #475569; }

.gc-shotmap3d { max-width: 900px; margin: 0 auto; }
.gc-shotmap3d .gl-rink3d { margin-top: -2.5%; }
#gc-playcard { max-width: 900px; margin: 10px auto 0; }

.pp-map3d { max-width: 860px; margin: 0 auto; }
.pp-map3d .gl-rink3d canvas { width: 100%; }
#pp-playcard { max-width: 860px; margin: 10px auto 0; }

/* The tilted rink wrap must never sit over the map toolbar — the select
   row wins hit-testing, and the profile rink drops the live page's
   negative pull-up. */
.pp-map-toolbar { position: relative; z-index: 6; }
.pp-map3d .gl-rink3d { margin-top: 0; }

.gc-sec-head { display: flex; align-items: center; justify-content: space-between; flex-wrap: wrap; gap: 10px; }
.gc-sec-head .gc-section-title { margin-bottom: 0; }
.gc-per-tabs { margin-left: auto; }

.pp-gd-ap { background: rgba(220,38,38,0.85); }
.pp-gd-a { background: rgba(234,88,12,0.75); }
.pp-gd-b { background: rgba(217,119,6,0.65); }
.pp-gd-c { background: rgba(100,116,139,0.5); }
.pp-map-grades { display: inline-flex; align-items: center; gap: 4px; flex-wrap: wrap; }

.gc-stars { display: flex; gap: 16px; flex-wrap: wrap; }
.gc-star { flex: 1 1 180px; min-width: 160px; border: 1px solid rgba(15,23,42,0.1); border-radius: 10px; padding: 12px 14px; }
.gc-star-rank { display: flex; align-items: center; gap: 6px; font-size: 11px; font-weight: 800; text-transform: uppercase; letter-spacing: 0.05em; color: #5b6572; }
.gc-star-ico { display: inline-flex; width: 14px; height: 14px; color: var(--brand-primary); }
.gc-star-ico svg { width: 100%; height: 100%; }
.gc-star:first-child .gc-star-ico { color: #d4a017; }
.gc-star-name { font-size: 16px; font-weight: 800; color: #0f172a; margin-top: 4px; }
.gc-star-line { font-size: 12.5px; color: #475569; margin-top: 2px; font-variant-numeric: tabular-nums; }

.gl-stars-row { display: flex; flex-direction: column; gap: 10px; }
.gl-star { display: flex; align-items: center; gap: 10px; border: 1px solid rgba(15,23,42,0.1); border-radius: 10px; padding: 10px 14px; }
.gl-star-ico { display: inline-flex; width: 16px; height: 16px; color: #94a3b8; }
.gl-star.first .gl-star-ico { color: #d4a017; }
.gl-star-ico svg { width: 100%; height: 100%; }
.gl-star-rank { font-weight: 800; font-size: 14px; color: #5b6572; min-width: 14px; }
.gl-star-body { display: flex; flex-direction: column; }
.gl-star-body b { font-size: 15px; color: var(--text, #0f172a); }
.gl-star-line { font-size: 12px; color: var(--text-dim, #6b7280); font-variant-numeric: tabular-nums; }

.gc-str-group { display: inline-flex; gap: 4px; }
.gc-str-btn.active { background: var(--brand-primary); color: #fff; border-color: var(--brand-primary); }

.gc-att-group { display: inline-flex; align-items: center; gap: 4px; }
#gc-att-toggle.active { background: var(--brand-primary); color: #fff; border-color: var(--brand-primary); }

.splits-form { display: flex; gap: 24px; flex-wrap: wrap; padding: 2px 0 12px; font-size: 13.5px; color: #1e293b; font-variant-numeric: tabular-nums; }
.splits-form-label { font-size: 11px; font-weight: 800; text-transform: uppercase; letter-spacing: 0.05em; color: #5b6572; margin-right: 6px; }

.dash-leaders { margin-top: 14px; margin-bottom: 22px; }
.dash-leaders-title { font-size: 11px; font-weight: 800; text-transform: uppercase; letter-spacing: 0.05em; color: #5b6572; margin-bottom: 8px; }
.dash-leaders-row { display: flex; gap: 12px; flex-wrap: wrap; }
.dash-leader { flex: 1 1 150px; display: flex; flex-direction: column; border: 1px solid rgba(15,23,42,0.1); border-radius: 10px; padding: 10px 14px; text-decoration: none; }
.dash-leader:hover { border-color: var(--brand-primary); }
.dash-leader-label { font-size: 10.5px; font-weight: 800; text-transform: uppercase; letter-spacing: 0.05em; color: #5b6572; }
.dash-leader-name { font-size: 14.5px; font-weight: 700; color: #0f172a; margin-top: 2px; }
.dash-leader-val { font-size: 19px; font-weight: 800; color: var(--brand-primary); font-variant-numeric: tabular-nums; }

.rep-stat-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(120px, 1fr)); gap: 14px; }
.rep-stat-label { font-size: 10.5px; font-weight: 800; text-transform: uppercase; letter-spacing: 0.05em; color: #5b6572; }
.rep-stat-val { font-size: 24px; font-weight: 800; color: #0f172a; font-variant-numeric: tabular-nums; }
.rep-stat-rank { font-size: 11px; color: #475569; }
.rep-ice { display: flex; gap: 24px; flex-wrap: wrap; align-items: flex-start; }
.rep-ice-col { flex: 2 1 300px; min-width: 260px; }
.rep-ice-col--net { flex: 1 1 220px; }
.rep-ice-title { font-size: 12px; font-weight: 800; text-transform: uppercase; letter-spacing: 0.04em; color: #334155; margin-bottom: 6px; }
.rep-ice-note { font-size: 11px; margin-top: 4px; }
@media print {
  .rep-ice { flex-wrap: nowrap; }
  .rep-section { break-inside: avoid; }
}

/* iOS app webview: the native app supplies its own chrome — hide the web
   topnav and reclaim its height. */
body.in-app .topnav, body.in-app .nav-drawer, body.in-app .nav-drawer-backdrop { display: none !important; }
body.in-app main { padding-top: 0 !important; }

.gl-period-tabs { justify-content: center; margin: 0 0 10px; }
.gl-period-caption { text-align: center; font-size: 13px; font-weight: 700; color: var(--text-dim, #6b7280); margin-top: 8px; font-variant-numeric: tabular-nums; }

/* Goal splash — celebration card over the live page for ~8s. */
.gl-splash-backdrop {
  position: fixed; inset: 0; z-index: 300;
  background: rgba(15, 23, 42, 0.5);
  display: flex; align-items: center; justify-content: center;
  padding: 24px;
  animation: gl-splash-in 0.25s ease-out;
  cursor: pointer;
}
@keyframes gl-splash-in { from { opacity: 0; } to { opacity: 1; } }
.gl-splash-card {
  background: #fff; border-radius: 18px; overflow: hidden;
  width: min(400px, 92vw);
  box-shadow: 0 20px 60px rgba(0, 0, 0, 0.35);
  animation: gl-splash-pop 0.3s cubic-bezier(0.34, 1.4, 0.64, 1);
}
@keyframes gl-splash-pop { from { transform: scale(0.85); opacity: 0; } to { transform: scale(1); opacity: 1; } }
.gl-splash-band {
  color: #fff; font-weight: 900; font-size: 22px; letter-spacing: 0.14em;
  text-align: center; padding: 12px;
}
.gl-splash-body { padding: 16px 18px 18px; text-align: center; }
.gl-splash-who { font-size: 21px; font-weight: 800; color: #0f172a; }
.gl-splash-bits { font-size: 13.5px; color: #475569; margin-top: 4px; font-variant-numeric: tabular-nums; }
.gl-splash-assists { font-size: 13.5px; color: #475569; margin-top: 2px; }
.gl-splash-net { position: relative; margin: 12px auto 0; width: min(260px, 80%); }
.gl-splash-net img { width: 100%; display: block; border-radius: 10px; }
.gl-splash-dot {
  position: absolute; width: 16px; height: 16px; border-radius: 50%;
  background: #dc2626; border: 2.5px solid #fff;
  transform: translate(-50%, -50%);
  box-shadow: 0 0 0 4px rgba(220, 38, 38, 0.35);
}
.gl-splash-zone { font-size: 12.5px; font-weight: 700; color: #475569; margin-top: 6px; }

/* Right-catching goalie: mirror the net art (labels swap in JS). */
.net-flip { transform: scaleX(-1); }

/* Game-clock edit pencil next to the time */
.gc-clock-time-row { display: flex; align-items: center; justify-content: center; gap: 4px; }
.gc-clock-edit {
  background: none; border: 0; padding: 4px; border-radius: 6px;
  color: var(--text-dim, #5a6270); cursor: pointer; line-height: 0;
}
.gc-clock-edit:hover { color: var(--text, #1a1d23); background: var(--bg-soft, #f2f4f7); }
.gc-clock-edit svg { width: 14px; height: 14px; display: block; }

/* Pre-game scouting report */
.scout-meets { display: flex; gap: 8px; flex-wrap: wrap; margin-bottom: 14px; }
.scout-meet {
  display: inline-flex; flex-direction: column; align-items: center;
  padding: 7px 14px; border-radius: 10px;
  background: var(--bg-soft, #f6f7f9); border: 1px solid var(--border, #e2e5ea);
}
.scout-meet b { font-size: 14px; color: var(--text, #1a1d23); font-variant-numeric: tabular-nums; }
.scout-meet span { font-size: 11px; color: var(--text-dim, #5a6270); }
.scout-meet.w { border-color: rgba(34,197,94,.45); background: rgba(34,197,94,.07); }
.scout-meet.l { border-color: rgba(220,64,64,.35); background: rgba(220,64,64,.05); }
.scout-table td, .scout-table th { text-align: center; }
.scout-table td:first-child { text-align: left; font-weight: 700; }
.scout-grid { display: flex; gap: 16px; flex-wrap: wrap; margin-top: 16px; }
.scout-panel { flex: 1; min-width: 260px; }
.scout-panel-title { font-size: 11.5px; font-weight: 800; letter-spacing: .05em; text-transform: uppercase; color: var(--text-dim, #5a6270); margin-bottom: 6px; }
.scout-panel canvas { display: block; border: 1px solid var(--border-soft, #eef0f3); border-radius: 10px; }
.scout-scorers { display: grid; grid-template-columns: 1fr 1fr; gap: 4px 20px; }
.scout-scorer { display: flex; justify-content: space-between; font-size: 13.5px; padding: 4px 0; border-bottom: 1px solid var(--border-soft, #eef0f3); }
.scout-st { margin-top: 12px; font-size: 13.5px; color: var(--text, #1a1d23); }
@media print {
  body.scout-print > *:not(script) { visibility: hidden; }
  body.scout-print #scout-modal, body.scout-print #scout-modal * { visibility: visible; }
  body.scout-print #scout-modal { position: absolute; inset: 0; background: #fff; display: block; }
  body.scout-print #scout-modal .modal { box-shadow: none; width: 100%; max-width: none; max-height: none; }
  body.scout-print #scout-modal .modal-actions { display: none; }
}

/* Milestone celebration on the live page */
.gl-splash-milestone {
  background: #f5b301; color: #3a2c00;
  text-align: center; padding: 7px 12px;
  font-family: Arial, Helvetica, sans-serif;
  font-size: 13px; font-weight: 900; letter-spacing: 0.12em;
}
.gl-mile-chip {
  display: inline-block; margin-left: 8px; padding: 1px 9px; border-radius: 999px;
  background: #fdf3d7; border: 1px solid #ecd28a; color: #7a5c00;
  font-size: 11px; font-weight: 800; letter-spacing: 0.02em; vertical-align: 1px;
}

/* ---- Fan reactions (public live page) ---- */
.gl-react-bar {
  position: fixed; left: 50%; transform: translateX(-50%); bottom: 14px;
  display: flex; gap: 2px; z-index: 290;
  background: rgba(17, 20, 30, 0.92);
  border: 1px solid rgba(255, 255, 255, 0.14);
  border-radius: 999px; padding: 5px 8px;
  box-shadow: 0 10px 32px rgba(0, 0, 0, 0.35);
  backdrop-filter: blur(8px); -webkit-backdrop-filter: blur(8px);
}
.gl-react-btn {
  display: flex; align-items: center; gap: 5px;
  background: transparent; border: 0; color: #fff; cursor: pointer;
  font-size: 12px; font-weight: 700; font-variant-numeric: tabular-nums;
  padding: 8px 9px; border-radius: 999px;
  -webkit-tap-highlight-color: transparent; touch-action: manipulation;
  transition: background 0.12s ease, transform 0.08s ease;
}
.gl-react-btn:active { background: rgba(255, 255, 255, 0.16); transform: scale(1.12); }
.gl-react-btn svg { width: 19px; height: 19px; display: block; }
.gl-react-count { color: rgba(255, 255, 255, 0.82); }
.gl-react-count:empty { display: none; }
.gl-react-clap  svg { color: #fbbf24; }
.gl-react-five  svg { color: #7dd3fc; }
.gl-react-fire  svg { color: #fb923c; }
.gl-react-heart svg { color: #fb7185; }
.gl-react-horn  svg { color: #a5b4fc; }
.gl-float-layer { position: fixed; inset: 0; pointer-events: none; z-index: 289; overflow: hidden; }
.gl-float { position: fixed; width: 26px; height: 26px; opacity: 0; animation: gl-float-up var(--dur, 1.6s) ease-out forwards; }
.gl-float svg { width: 100%; height: 100%; filter: drop-shadow(0 2px 6px rgba(0, 0, 0, 0.3)); }
@keyframes gl-float-up {
  0%   { transform: translate(0, 0) scale(0.7); opacity: 0; }
  12%  { opacity: 1; }
  100% { transform: translate(var(--dx, 0px), -180px) scale(1.15); opacity: 0; }
}
.gl-splash-react { display: flex; gap: 10px; justify-content: center; margin-top: 14px; }
.gl-splash-react button {
  display: flex; align-items: center; justify-content: center;
  width: 52px; height: 44px; border-radius: 12px; cursor: pointer;
  background: #f1f5f9; border: 1px solid #e2e8f0; color: #0f172a;
  -webkit-tap-highlight-color: transparent; touch-action: manipulation;
  transition: transform 0.08s ease, background 0.12s ease;
}
.gl-splash-react button:active { transform: scale(1.15); background: #e2e8f0; }
.gl-splash-react button svg { width: 22px; height: 22px; }
.gl-goal-reacts { display: flex; gap: 8px; justify-content: center; margin-top: 8px; }
/* Tappable per-play react row on the play card */
.gl-goal-reactrow { display: flex; gap: 6px; justify-content: center; margin-top: 10px; }
.gl-gr-btn {
  display: inline-flex; align-items: center; gap: 4px;
  background: #f1f5f9; border: 1px solid #e2e8f0; border-radius: 999px;
  padding: 6px 10px; cursor: pointer; color: #0f172a;
  font-size: 12px; font-weight: 700; font-variant-numeric: tabular-nums;
  -webkit-tap-highlight-color: transparent; touch-action: manipulation;
  transition: transform 0.08s ease, background 0.12s ease;
}
.gl-gr-btn:active { transform: scale(1.12); background: #e2e8f0; }
.gl-gr-btn svg { width: 16px; height: 16px; display: block; }
.gl-gr-count:empty { display: none; }
/* Quick-clap chip on scoring feed rows */
.gl-row-react {
  display: inline-flex; align-items: center; gap: 4px; align-self: center;
  background: transparent; border: 1px solid #e2e8f0; border-radius: 999px;
  padding: 5px 9px; cursor: pointer; color: #475569;
  font-size: 12px; font-weight: 700; font-variant-numeric: tabular-nums;
  -webkit-tap-highlight-color: transparent; touch-action: manipulation;
  transition: transform 0.08s ease, background 0.12s ease;
}
.gl-row-react:active { transform: scale(1.12); background: #f1f5f9; }
.gl-row-react svg { width: 15px; height: 15px; display: block; }
.gl-goal-react {
  display: inline-flex; align-items: center; gap: 4px;
  font-size: 12px; font-weight: 700; color: #475569; font-variant-numeric: tabular-nums;
}
.gl-goal-react svg { width: 15px; height: 15px; }
@media (prefers-reduced-motion: reduce) {
  .gl-splash-backdrop, .gl-splash-card { animation: none; }
  .gl-float { animation-duration: 0.6s; }
}

/* ============ Ask a Pro ============ */
.pros-page { max-width: 860px; }
.pros-sub { color: var(--text-dim); font-size: 14px; margin: -6px 0 20px; }

/* Stories row — the one hero surface on this page, so the brand
 * violet→cyan gradient ring is allowed here (STYLE.md carve-out). */
.pro-stories { display: flex; gap: 22px; overflow-x: auto; padding: 6px 2px 14px; }
.pro-story { background: none; border: 0; padding: 0; cursor: pointer; text-align: center; flex: 0 0 auto; width: 96px; }
.pro-ring { position: relative; display: inline-block; padding: 4px; border-radius: 50%; background: var(--border); }
.pro-ring.is-online { background: linear-gradient(135deg, #7c5cff, #22d3ee); }
.pro-ring img { display: block; width: 76px; height: 76px; border-radius: 50%; object-fit: cover; border: 3px solid #fff; }
.pro-presence { position: absolute; right: 4px; bottom: 4px; width: 16px; height: 16px; border-radius: 50%; background: #9aa3af; border: 3px solid #fff; }
.pro-presence.on { background: #22c55e; }
.pro-story-name { display: block; margin-top: 7px; font-size: 13px; font-weight: 700; color: var(--text); }
.pro-story-status { display: block; font-size: 11px; color: var(--text-dim); margin-top: 1px; }
.pro-story-status.on { color: #16a34a; font-weight: 700; }
.pro-story:hover .pro-ring img { filter: brightness(1.05); }

.pros-empty { color: var(--text-dim); font-size: 14px; padding: 18px 4px; }

/* Modals (self-contained backdrop; .modal styling reused for the card) */
.pros-backdrop { position: fixed; inset: 0; background: rgba(0,0,0,.45); display: grid; place-items: center; z-index: 120; padding: 16px; }
.pros-backdrop[hidden] { display: none; }
.pro-modal-card { width: 520px; max-width: 94vw; max-height: 88vh; overflow-y: auto; }
.pro-modal-head { display: flex; align-items: center; gap: 14px; margin-bottom: 12px; }
.pro-modal-head img { width: 64px; height: 64px; border-radius: 50%; object-fit: cover; flex: 0 0 auto; }
.pro-modal-head.compact img { width: 40px; height: 40px; }
.pro-modal-head h2 { margin: 0; font-size: 20px; }
.pro-m-tag { font-size: 13px; color: var(--text-dim); }
.pro-m-site { font-size: 12px; font-weight: 700; color: var(--brand-primary, #7c5cff); text-decoration: none; }
.pro-m-status { margin-left: auto; font-size: 11px; font-weight: 800; text-transform: uppercase; letter-spacing: .5px; color: var(--text-dim); }
.pro-m-status.on { color: #16a34a; }
.pro-m-bio { font-size: 14px; line-height: 1.55; color: var(--text); margin: 0 0 14px; }
.pro-ask textarea { margin-top: 10px; }
.pro-ask .modal-actions { display: flex; justify-content: flex-end; gap: 8px; margin-top: 12px; }

/* Thread rows + messages */
.th-row { display: flex; align-items: center; gap: 12px; width: 100%; text-align: left; cursor: pointer; margin-bottom: 8px; padding: 12px 14px; }
.th-row-img { width: 40px; height: 40px; border-radius: 50%; object-fit: cover; flex: 0 0 auto; }
.th-row-main { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 2px; font-size: 14px; }
.th-row-last { color: var(--text-dim); font-size: 13px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.th-row-when { font-size: 11px; color: var(--text-dim); flex: 0 0 auto; }
.th-chip { display: inline-block; font-size: 10px; font-weight: 800; text-transform: uppercase; letter-spacing: .4px; color: var(--brand-primary, #7c5cff); background: color-mix(in srgb, var(--brand-primary, #7c5cff) 12%, #fff); border-radius: 4px; padding: 2px 7px; width: fit-content; }
.th-messages { max-height: 320px; overflow-y: auto; display: flex; flex-direction: column; gap: 10px; margin: 12px 0; }
.th-msg-who { font-size: 12px; font-weight: 700; color: var(--text); }
.th-msg-who span { font-weight: 400; color: var(--text-dim); margin-left: 6px; font-size: 11px; }
.th-msg-body { font-size: 14px; line-height: 1.5; white-space: pre-wrap; }
.th-shared-card { display: flex; gap: 12px; border: 1px solid var(--border); border-radius: 8px; padding: 12px; margin-bottom: 6px; align-items: flex-start; background: var(--surface, #fafafa); }
.th-shared-card img { width: 96px; border-radius: 6px; flex: 0 0 auto; }
.th-shared-kicker { font-size: 10px; font-weight: 800; text-transform: uppercase; letter-spacing: .5px; color: var(--brand-primary, #7c5cff); }
.th-shared-notes { font-size: 13px; color: var(--text-dim); margin-top: 4px; }
.th-shared-list { margin: 6px 0 0; padding-left: 18px; font-size: 13px; }
.th-shared-list span { color: var(--text-dim); }
.thread-modal .modal-actions { display: flex; justify-content: flex-end; margin-top: 10px; }

/* Coaches' room — forum feed. Flat surfaces, hairlines, initials
 * avatars; brand color only on interactive accents (STYLE.md). */
.cm-head { display: flex; align-items: center; justify-content: space-between; gap: 12px; margin-top: 30px; }
.cm-head .pp-sec-title { margin: 0; }
.cm-count { font-weight: 400; color: var(--text-dim); font-size: 13px; text-transform: none; letter-spacing: 0; }
.cm-search {
  width: 220px; border: 1px solid var(--border); border-radius: 8px;
  padding: 8px 12px; font-family: inherit; font-size: 13px; outline: none;
  background: #fff; color: var(--text);
}
.cm-search:focus { border-color: var(--brand-primary, #7c5cff); }

.cm-avatar {
  display: inline-flex; align-items: center; justify-content: center;
  width: 34px; height: 34px; border-radius: 50%; flex: 0 0 auto;
  color: #fff; font-size: 12px; font-weight: 800; letter-spacing: .3px;
  user-select: none;
}
.cm-avatar--sm { width: 26px; height: 26px; font-size: 10px; }
.cm-avatar--me { background: var(--brand-primary, #7c5cff); }

.community-composer { padding: 14px 16px; margin: 14px 0 18px; }
.cm-composer-row { display: flex; gap: 10px; align-items: center; }
.cm-composer-row input[type=text] {
  flex: 1; border: 1px solid var(--border); border-radius: 999px;
  padding: 10px 16px; font-family: inherit; font-size: 14px; outline: none;
  background: var(--bg-soft, #f6f7f9); color: var(--text);
}
.cm-composer-row input[type=text]:focus { border-color: var(--brand-primary, #7c5cff); background: #fff; }
.cm-composer-more { display: none; margin-top: 10px; padding-left: 44px; }
.community-composer.is-open .cm-composer-more { display: block; }
.cm-composer-more textarea {
  width: 100%; border: 1px solid var(--border); border-radius: 10px;
  padding: 10px 12px; font-family: inherit; font-size: 14px; outline: none;
  margin-bottom: 8px; resize: vertical; color: var(--text);
}
.cm-composer-more textarea:focus { border-color: var(--brand-primary, #7c5cff); }
.cm-row { display: flex; gap: 8px; align-items: center; }
.cm-row select { border: 1px solid var(--border); border-radius: 8px; padding: 8px 10px; font-family: inherit; font-size: 13px; background: #fff; color: var(--text); }
.cm-row input[type=text] { flex: 1; border: 1px solid var(--border); border-radius: 8px; padding: 9px 12px; font-family: inherit; font-size: 14px; outline: none; }
.cm-row input[type=text]:focus { border-color: var(--brand-primary, #7c5cff); }

.cm-post {
  background: #fff; border: 1px solid var(--border); border-radius: 12px;
  padding: 16px 18px 12px; margin-bottom: 12px;
}
.cm-post-top { display: flex; align-items: center; gap: 10px; margin-bottom: 10px; }
.cm-post-who { display: flex; flex-direction: column; min-width: 0; line-height: 1.25; }
.cm-post-who b { font-size: 13.5px; color: var(--text); }
.cm-post-team { font-size: 12px; color: var(--text-dim); }
.cm-post-when { margin-left: auto; font-size: 12px; color: var(--text-dim); flex: 0 0 auto; }
.cm-post-title { margin: 0 0 6px; font-size: 15.5px; font-weight: 700; color: var(--text); line-height: 1.35; }
.cm-post-body {
  font-size: 14px; line-height: 1.55; color: var(--text);
  white-space: pre-wrap; cursor: pointer;
  display: -webkit-box; -webkit-line-clamp: 3; -webkit-box-orient: vertical; overflow: hidden;
}
.cm-post-body.is-open { display: block; -webkit-line-clamp: unset; }
.cm-post-attach { margin-top: 8px; }
.cm-post-foot { display: flex; align-items: center; margin-top: 10px; padding-top: 10px; border-top: 1px solid var(--border); }
.cm-replies-btn {
  display: inline-flex; align-items: center; gap: 6px;
  background: none; border: 0; cursor: pointer; padding: 2px 0;
  font-size: 12.5px; font-weight: 700; color: var(--brand-primary, #7c5cff);
  font-family: inherit;
}
.cm-replies-btn svg { width: 15px; height: 15px; }
.cm-replies { margin-top: 12px; padding-top: 4px; display: flex; flex-direction: column; gap: 12px; }
.cm-reply { display: flex; gap: 10px; padding-left: 10px; border-left: 2px solid var(--border); }
.cm-reply-main { min-width: 0; }
.cm-reply-who { display: flex; align-items: baseline; gap: 8px; font-size: 12.5px; }
.cm-reply-who b { color: var(--text); }
.cm-reply-who span { color: var(--text-dim); font-size: 11.5px; }
.cm-reply-body { font-size: 13.5px; line-height: 1.5; color: var(--text); white-space: pre-wrap; margin-top: 2px; }
.cm-reply-composer { margin-top: 2px; padding-left: 10px; }
.cm-more-wrap { text-align: center; margin: 6px 0 20px; }
.cm-more-btn { min-width: 200px; }

@media (max-width: 640px) {
  .pro-stories { gap: 14px; }
  .pro-story { width: 82px; }
  .pro-ring img { width: 64px; height: 64px; }
  .cm-head { flex-direction: column; align-items: flex-start; gap: 8px; }
  .cm-search { width: 100%; }
  .cm-post { padding: 13px 14px 10px; }
}

/* "Practice in progress" live banner on the plans landing */
#run-live-banner {
  display: flex; align-items: center; gap: 10px;
  width: 100%; margin: 0 0 16px; padding: 12px 16px;
  background: var(--brand-primary, #7c5cff); color: #fff;
  border: 0; border-radius: 12px; cursor: pointer;
  font-family: inherit; font-size: 14px; text-align: left;
}
#run-live-banner b { font-weight: 800; letter-spacing: .2px; }
#run-live-banner .run-live-name { opacity: .92; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
#run-live-banner .run-live-join { margin-left: auto; font-weight: 800; flex: 0 0 auto; }
.run-live-dot {
  width: 9px; height: 9px; border-radius: 50%; background: #4ade80; flex: 0 0 auto;
  animation: run-live-pulse 1.6s ease-in-out infinite;
}
@keyframes run-live-pulse { 0%,100% { opacity: 1; } 50% { opacity: .35; } }

/* Partner invite branding row */
.partners-brand-row { display: block; }
.partners-brand-row .pf-color { display: inline-flex; align-items: center; gap: 8px; margin-right: 18px; font-size: 13px; }
.partners-brand-row .pf-color input[type=color] { width: 42px; height: 30px; border: 1px solid var(--border); border-radius: 6px; padding: 2px; background: #fff; cursor: pointer; }
.partners-brand-row .pf-logo { display: inline-flex; align-items: center; gap: 10px; font-size: 13px; }
.partners-brand-row .pf-logo img { width: 34px; height: 34px; border-radius: 8px; object-fit: cover; border: 1px solid var(--border); }

/* Game Center — season series strip */
.gc-series-row { display: flex; gap: 8px; overflow-x: auto; padding: 2px 0 6px; }
.gc-series-chip {
  display: inline-flex; align-items: center; gap: 5px; flex: 0 0 auto;
  border: 1px solid var(--border); background: #fff; border-radius: 999px;
  padding: 6px 13px; font-size: 12.5px; color: var(--text-dim);
  font-family: inherit; cursor: pointer;
}
.gc-series-chip:hover { border-color: var(--brand-primary, #7c5cff); color: var(--text); }
.gc-series-res { font-weight: 800; }
.gc-series-res.is-w { color: var(--green, #1f9e5a); }
.gc-series-res.is-l { color: var(--danger, #dc2626); }
.gc-series-res.is-t { color: var(--text-dim); }

/* ============================================================
   Site footer — every standard page (Ian 2026-08-30). Flat, light
   surface, high-contrast text per docs/STYLE.md. Hidden on the drill
   board (the floating dock owns that bottom edge) and on public share
   pages, which have their own branded footer.
   ============================================================ */
.site-footer {
  margin-top: 48px;
  border-top: 1px solid var(--border, #d8dce1);
  background: #fff;
}
.site-footer-inner {
  max-width: 1180px;
  margin: 0 auto;
  padding: 22px 24px 26px;
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 12px 22px;
}
.site-footer-brand {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  min-width: 0;
}
.site-footer-mark { display: inline-flex; color: var(--brand-primary, #d4302b); }
.site-footer-mark svg { width: 18px; height: 18px; }
.site-footer-name { font-weight: 800; font-size: 14px; letter-spacing: 0.2px; color: #16181d; }
.site-footer-tag { font-size: 12px; color: #3d434c; }
.site-footer-ad { margin-left: auto; }
.site-footer-links {
  display: inline-flex;
  align-items: center;
  gap: 16px;
}
.site-footer-links a {
  font-size: 12.5px;
  font-weight: 600;
  color: #2b2f36;
  text-decoration: none;
}
.site-footer-links a:hover { color: var(--brand-primary, #d4302b); }
.site-footer-copy { font-size: 12px; color: #3d434c; }
@media (max-width: 720px) {
  .site-footer-inner { flex-direction: column; align-items: flex-start; gap: 10px; }
  .site-footer-ad { margin-left: 0; }
}
/* Surfaces that own their own bottom chrome. */
body.route-drill .site-footer,
body.route-drill-share .site-footer,
body.route-lineup-share .site-footer,
body.route-login .site-footer { display: none; }

/* Impersonation banner — fixed pill while a platform admin works inside
   another account (Sign in as, /admin/partners). */
#impersonation-banner {
  position: fixed;
  left: 16px;
  bottom: 16px;
  z-index: 4000;
  display: inline-flex;
  align-items: center;
  gap: 12px;
  padding: 10px 14px;
  border-radius: 12px;
  background: #16181d;
  color: #fff;
  font-size: 13px;
  box-shadow: 0 8px 24px -8px rgba(0,0,0,.45);
}
#impersonation-banner b { font-weight: 700; }
#impersonation-banner button {
  border: 0;
  border-radius: 999px;
  padding: 6px 12px;
  font-size: 12px;
  font-weight: 700;
  background: #fff;
  color: #16181d;
  cursor: pointer;
}
#impersonation-banner button:hover { background: #e8eaee; }
/* The drill board's dock owns the bottom-left corner — lift the pill. */
body.route-drill #impersonation-banner { bottom: 84px; }

/* ============ Offer ads (pro partner lead capture, 2026-09-03) ======
   The pill reads native — FREE chip + offer headline + "More info" —
   and opens an in-app modal with the partner pitch + a name/email
   form. Flat brand styling per docs/STYLE.md (no gradients on chrome). */
.pc-ad--offer {
  cursor: pointer;
  font-family: inherit;
}
.pc-ad-free {
  background: var(--brand-primary, #d4302b);
  color: #fff;
  font-size: 10px;
  font-weight: 800;
  letter-spacing: 0.08em;
  padding: 2px 7px;
  border-radius: 999px;
}
.pc-ad-offer-title { font-weight: 700; }
.pc-ad-more {
  font-weight: 600;
  text-decoration: underline;
  text-underline-offset: 2px;
  opacity: 0.85;
}

.pc-offer-bg {
  position: fixed;
  inset: 0;
  background: rgba(10, 12, 15, 0.66);
  z-index: 1200;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 16px;
}
.pc-offer {
  position: relative;
  background: #fff;
  color: var(--text, #16181d);
  border-radius: 18px;
  max-width: 560px;
  width: 100%;
  max-height: 92vh;
  overflow-y: auto;
  box-shadow: 0 32px 80px rgba(0, 0, 0, 0.45);
}
.pc-offer-close {
  position: absolute;
  top: 12px;
  right: 14px;
  z-index: 2;
  border: 0;
  background: rgba(255, 255, 255, 0.12);
  border-radius: 999px;
  width: 34px;
  height: 34px;
  font-size: 22px;
  line-height: 1;
  color: rgba(255, 255, 255, 0.85);
  cursor: pointer;
}
/* Dark broadcast-style hero — the poster moment. Deliberate dark band
   (matches the Live Activity / scoreboard look), flat, no gradients. */
.pc-offer-hero {
  background: #14171c;
  color: #fff;
  text-align: center;
  padding: 36px 30px 30px;
}
.pc-offer-free {
  display: inline-block;
  background: var(--brand-primary, #d4302b);
  color: #fff;
  font-size: 12px;
  font-weight: 800;
  letter-spacing: 0.16em;
  padding: 5px 14px;
  border-radius: 999px;
  margin-bottom: 16px;
}
.pc-offer-hero h2 {
  margin: 0 auto;
  max-width: 15ch;
  font-family: 'acumin-pro-semi-condensed', 'Anton', Impact, system-ui, sans-serif;
  font-size: 40px;
  font-weight: 800;
  line-height: 1.02;
  text-transform: uppercase;
  letter-spacing: 0.01em;
}
.pc-offer-hero .pc-offer-sub {
  margin: 14px auto 0;
  max-width: 44ch;
  font-size: 14px;
  line-height: 1.5;
  color: rgba(255, 255, 255, 0.78);
}
.pc-offer-content { padding: 24px 30px 22px; }
.pc-offer-body {
  margin: 0 0 14px;
  font-size: 15.5px;
  line-height: 1.55;
}
.pc-offer-bullets {
  list-style: none;
  margin: 0 0 18px;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 9px;
}
.pc-offer-bullets li {
  display: flex;
  align-items: flex-start;
  gap: 10px;
  font-size: 15px;
  line-height: 1.4;
  font-weight: 500;
}
.pc-offer-bullets svg {
  flex: none;
  margin-top: 2px;
  color: var(--brand-primary, #d4302b);
}
.pc-offer-form {
  display: flex;
  flex-direction: column;
  gap: 10px;
}
.pc-offer-form input {
  border: 1.5px solid var(--border, #d0d4d9);
  border-radius: 11px;
  padding: 14px 15px;
  font-size: 16px;
  font-family: inherit;
  color: var(--text, #16181d);
  background: #fff;
}
.pc-offer-form input:focus {
  outline: 2px solid var(--brand-primary, #d4302b);
  outline-offset: -1px;
  border-color: transparent;
}
.pc-offer-cta {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 9px;
  border: 0;
  border-radius: 11px;
  background: var(--brand-primary, #d4302b);
  color: #fff;
  font-size: 16.5px;
  font-weight: 800;
  font-family: inherit;
  padding: 15px;
  cursor: pointer;
}
.pc-offer-cta svg { display: block; }
.pc-offer-cta:disabled { opacity: 0.6; cursor: default; }
.pc-offer-fine {
  margin: 12px 0 0;
  font-size: 12px;
  text-align: center;
  color: #4a5058;
}
.pc-offer-done {
  text-align: center;
  padding: 46px 30px 42px;
  background: #14171c;
  color: #fff;
  border-radius: 18px;
}
.pc-offer-done h2 {
  margin: 0 0 8px;
  font-family: 'acumin-pro-semi-condensed', 'Anton', Impact, system-ui, sans-serif;
  font-size: 30px;
  text-transform: uppercase;
  line-height: 1.1;
}
.pc-offer-done .pc-offer-sub { color: rgba(255, 255, 255, 0.75); margin: 0; }
@media (max-width: 480px) {
  .pc-offer-hero h2 { font-size: 32px; }
  .pc-offer-hero { padding: 30px 22px 24px; }
  .pc-offer-content { padding: 20px 22px 18px; }
}

/* Offer block on the public live-follow page — boxless, centered,
   below the rink (Ian 2026-09-03: no card border, small arrow CTA). */
.gl-offer {
  text-align: center;
  padding: 20px 16px 2px;
}
.gl-offer-top {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  margin-bottom: 7px;
}
.gl-offer-kicker {
  font-size: 11px;
  font-weight: 800;
  letter-spacing: 0.13em;
  text-transform: uppercase;
  color: var(--brand-primary, #d4302b);
}
.gl-offer-title {
  display: block;
  max-width: 44ch;
  margin: 0 auto 12px;
  font-family: 'acumin-pro-semi-condensed', 'Anton', Impact, system-ui, sans-serif;
  font-size: 17px;
  font-weight: 800;
  line-height: 1.05;
  text-transform: uppercase;
  color: var(--text, #16181d);
}
.gl-offer-cta {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  background: var(--brand-primary, #d4302b);
  color: #fff;
  border: 0;
  border-radius: 999px;
  padding: 9px 18px;
  font-size: 13.5px;
  font-weight: 700;
  font-family: inherit;
  cursor: pointer;
}
.gl-offer-cta svg { display: block; }

/* Pro avatar — small round headshot on the offer card + modal hero. */
.gl-offer-avatar {
  width: 30px;
  height: 30px;
  border-radius: 999px;
  object-fit: cover;
  display: block;
  border: 1.5px solid var(--brand-primary, #d4302b);
}
.pc-offer-avatar {
  width: 68px;
  height: 68px;
  border-radius: 999px;
  object-fit: cover;
  display: block;
  margin: 0 auto 12px;
  border: 2.5px solid rgba(255, 255, 255, 0.9);
}

/* Offer card spacing on tool pages: clear the drill board's floating
   toolbars at rest; separate from the plans toolbar. */

body.route-plans [data-offer-card] .gl-offer { padding: 8px 16px 14px; }

/* Drill board: the offer lives with the tags + notes cluster (Ian
   2026-09-04) — hidden while that cluster is parked in canvas-wrap,
   shown inside the drawer's NOTES panel as a stacked mini-card, and
   below the board only in notes-below mode. */
body.route-drill .canvas-wrap > [data-offer-card] { display: none; }
body.route-drill.drill-notes-below.drill-mode-draw .canvas-wrap > [data-offer-card] { display: block; }
body.route-drill #panel-notes [data-offer-card] { margin: 12px 0 0; }
body.route-drill #panel-notes [data-offer-card] .gl-offer {
  flex-direction: column;
  gap: 10px;
  padding: 14px 12px;
  background: var(--dock-panel-2);
  border: 1px solid var(--dock-line);
  border-radius: 10px;
}
/* Compact one-line offer row (notes-below mode under the board). */
body.route-drill [data-offer-card] .gl-offer {
  display: flex;
  align-items: center;
  justify-content: center;
  flex-wrap: wrap;
  gap: 8px 14px;
  padding: 14px 16px;
}
body.route-drill [data-offer-card] .gl-offer-top { margin-bottom: 0; }
body.route-drill [data-offer-card] .gl-offer-avatar { width: 22px; height: 22px; }
body.route-drill [data-offer-card] .gl-offer-kicker { font-size: 10px; }
body.route-drill [data-offer-card] .gl-offer-title {
  font-size: 13px;
  margin: 0;
  max-width: none;
}
body.route-drill [data-offer-card] .gl-offer-cta {
  padding: 6px 12px;
  font-size: 11.5px;
}

/* Small screens: the board fills the viewport and everything below it
   sits in the floating-bar band — no clean home for the offer row, so
   it stays desktop/iPad-landscape only. Other surfaces cover mobile. */
@media (max-width: 1023px) {
  body.route-drill [data-offer-card] { display: none; }
}

/* ===== Classroom community + course questions (2026-09-05) ===== */
.cr-community { margin-top: 40px; }
.cr-community-heading { font-size: 18px; margin: 0 0 2px; }
.cr-community .sub { margin-bottom: 12px; }
#cr-community-feed, #cr-q-list { display: flex; flex-direction: column; }
.cr-q-row {
  display: flex;
  align-items: center;
  gap: 12px;
  width: 100%;
  text-align: left;
  background: none;
  border: none;
  border-top: 1px solid rgba(0, 0, 0, 0.08);
  padding: 12px 4px;
  cursor: pointer;
  font: inherit;
  color: var(--text, #16181d);
}
.cr-q-row:hover { background: rgba(0, 0, 0, 0.025); }
.cr-q-row-main { display: flex; flex-direction: column; gap: 3px; min-width: 0; flex: 1; }
.cr-q-title { font-weight: 700; font-size: 14px; }
.cr-q-body-preview {
  font-size: 13px;
  color: var(--text-mid, #4b5058);
  overflow: hidden;
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
}
.cr-q-meta { font-size: 12px; color: var(--text-mid, #4b5058); }
.cr-q-course { font-weight: 600; }
.cr-q-replies { font-size: 12px; color: var(--text-mid, #4b5058); white-space: nowrap; }
.cr-pro-chip {
  display: inline-block;
  font-size: 9.5px;
  font-weight: 800;
  letter-spacing: 0.6px;
  padding: 1px 6px;
  border-radius: 999px;
  background: var(--brand-primary, #16181d);
  color: #fff;
  vertical-align: 2px;
}
.cr-questions { margin-top: 36px; max-width: 780px; }
.cr-q-form { display: flex; flex-direction: column; gap: 8px; margin: 12px 0 18px; }
.cr-q-form input[type="text"], .cr-q-form textarea, .cr-q-reply-form textarea {
  width: 100%;
  padding: 9px 12px;
  border: 1px solid rgba(0, 0, 0, 0.16);
  border-radius: 8px;
  font: inherit;
  font-size: 14px;
}
.cr-q-form-row { display: flex; gap: 8px; align-items: center; justify-content: space-between; }
.cr-q-form-row select {
  padding: 8px 10px;
  border: 1px solid rgba(0, 0, 0, 0.16);
  border-radius: 8px;
  font: inherit;
  font-size: 13px;
  max-width: 60%;
}
.cr-q-empty, .cr-q-locked { padding: 16px 4px; color: var(--text-mid, #4b5058); font-size: 14px; }
.cr-q-locked { display: flex; align-items: center; gap: 8px; }
.cr-q-upgrade-link {
  background: none;
  border: none;
  padding: 0;
  font: inherit;
  color: var(--brand-primary, #16181d);
  font-weight: 700;
  cursor: pointer;
  text-decoration: underline;
}
.cr-q-replies-wrap { padding: 0 4px 14px 16px; border-top: 1px dashed rgba(0, 0, 0, 0.08); }
.cr-q-reply { display: flex; flex-direction: column; gap: 2px; padding: 10px 0 0; }
.cr-q-reply--pro { border-left: 3px solid var(--brand-primary, #16181d); padding-left: 10px; }
.cr-q-reply-head { font-size: 12px; font-weight: 700; }
.cr-q-reply-body { font-size: 14px; }
.cr-q-reply-form { display: flex; gap: 8px; margin-top: 12px; align-items: flex-start; }

/* Community phase 1: spaces, attachments, accepted answers (2026-09-05) */
.cr-space-chips { display: flex; flex-wrap: wrap; gap: 6px; margin: 4px 0 8px; }
.cr-chip {
  font: inherit;
  font-size: 12px;
  font-weight: 700;
  padding: 5px 11px;
  border-radius: 999px;
  border: 1px solid rgba(0, 0, 0, 0.14);
  background: #fff;
  color: var(--text, #16181d);
  cursor: pointer;
}
.cr-chip.on { background: var(--brand-primary, #16181d); border-color: var(--brand-primary, #16181d); color: #fff; }
.cr-q-attach { display: flex; gap: 6px; flex-wrap: wrap; align-items: center; min-width: 0; }
.cr-q-attach select { padding: 8px 10px; border: 1px solid rgba(0, 0, 0, 0.16); border-radius: 8px; font: inherit; font-size: 13px; max-width: 220px; }
.cr-q-attach-line { display: block; margin: 2px 0; }
.cr-answered-chip {
  display: inline-flex; align-items: center; gap: 4px;
  font-size: 10.5px; font-weight: 800; letter-spacing: 0.4px; text-transform: uppercase;
  color: #1a7f3c; background: rgba(26, 127, 60, 0.1); border-radius: 999px; padding: 2px 8px; vertical-align: 2px;
}
.cr-q-reply--accepted { border-left: 3px solid #1a7f3c; padding-left: 10px; background: rgba(26, 127, 60, 0.04); border-radius: 0 6px 6px 0; }
.cr-q-accept {
  background: none; border: none; padding: 0; margin-left: 8px;
  font: inherit; font-size: 12px; font-weight: 600; color: var(--brand-primary, #16181d);
  cursor: pointer; text-decoration: underline;
}
.cr-q-open-course { display: inline-block; margin-top: 10px; font-size: 13px; font-weight: 700; color: var(--brand-primary, #16181d); }
#cr-community .th-shared-card, #cr-questions .th-shared-card { margin: 10px 0 6px; }

/* Community phase 2: levels, streaks, likes, rituals, leaderboard (2026-09-05) */
.cr-community-layout { display: grid; grid-template-columns: minmax(0, 1fr) 300px; gap: 28px; align-items: start; }
@media (max-width: 900px) { .cr-community-layout { grid-template-columns: 1fr; } }
.cr-q-row[role="button"] { cursor: pointer; }
.cr-q-side { display: flex; flex-direction: column; align-items: flex-end; gap: 6px; }
.cr-level-chip, .cr-streak-chip {
  display: inline-block; margin-left: 6px; font-size: 10.5px; font-weight: 700; letter-spacing: 0.2px;
  padding: 1px 7px; border-radius: 999px; border: 1px solid rgba(0, 0, 0, 0.14); color: var(--text, #16181d); background: #fff;
  vertical-align: 1px;
}
.cr-streak-chip { border-color: transparent; background: rgba(0, 0, 0, 0.06); }
.cr-ritual-chip {
  display: inline-block; margin-right: 8px; font-size: 10px; font-weight: 800; letter-spacing: 0.6px; text-transform: uppercase;
  padding: 2px 7px; border-radius: 4px; background: var(--brand-primary, #16181d); color: #fff; vertical-align: 2px;
}
.cr-q-row--ritual { background: rgba(0, 0, 0, 0.025); border-radius: 8px; }
.cr-like {
  display: inline-flex; align-items: center; gap: 4px; padding: 3px 8px; border-radius: 999px;
  border: 1px solid rgba(0, 0, 0, 0.14); background: #fff; color: var(--text, #16181d); font: inherit; font-size: 12px; cursor: pointer;
}
.cr-like.on { background: var(--brand-primary, #16181d); border-color: var(--brand-primary, #16181d); color: #fff; }
.cr-q-reply-head .cr-like { margin-left: 8px; vertical-align: middle; }
.cr-leaderboard { border: 1px solid rgba(0, 0, 0, 0.1); border-radius: 12px; padding: 14px 16px; position: sticky; top: 16px; }
.cr-lb-head { display: flex; align-items: baseline; justify-content: space-between; gap: 8px; }
.cr-lb-head h3 { margin: 0; font-size: 15px; }
.cr-lb-scope { font-size: 12px; color: var(--text-mid, #4b5058); }
.cr-lb-chips { display: flex; flex-wrap: wrap; gap: 5px; margin: 10px 0 8px; align-items: center; }
.cr-chip--sm { font-size: 11px; padding: 3px 9px; }
.cr-lb-sep { width: 1px; height: 16px; background: rgba(0, 0, 0, 0.12); margin: 0 3px; }
.cr-lb-list { list-style: none; margin: 0; padding: 0; }
.cr-lb-list li { display: grid; grid-template-columns: 22px minmax(0, 1fr) auto; gap: 8px; align-items: center; padding: 7px 0; border-top: 1px solid rgba(0, 0, 0, 0.07); font-size: 13px; }
.cr-lb-list li.me { font-weight: 700; }
.cr-lb-rank { font-weight: 800; font-variant-numeric: tabular-nums; color: var(--text-mid, #4b5058); }
.cr-lb-name { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.cr-lb-name .cr-level-chip { margin-left: 6px; }
.cr-lb-pts { font-variant-numeric: tabular-nums; white-space: nowrap; }
.cr-lb-me { margin-top: 10px; padding-top: 10px; border-top: 1px solid rgba(0, 0, 0, 0.12); font-size: 13px; }
.cr-lb-how { display: block; margin-top: 6px; font-size: 11px; color: var(--text-mid, #4b5058); }

/* Community phase 3: challenges, moderation, public solved pages (2026-09-05) */
.cr-challenges { margin-top: 36px; }
.cr-state-pill { margin-left: auto; font-size: 10.5px; font-weight: 800; letter-spacing: 0.4px; text-transform: uppercase; padding: 2px 8px; border-radius: 999px; border: 1px solid rgba(0,0,0,0.14); }
.cr-state-live { background: var(--brand-primary, #16181d); border-color: var(--brand-primary, #16181d); color: #fff; }
.cr-kicker { display: block; font-size: 11px; font-weight: 800; letter-spacing: 0.8px; text-transform: uppercase; color: var(--brand-primary, #16181d); margin-bottom: 6px; }
.cr-ch-weeks { list-style: none; margin: 22px 0 0; padding: 0; max-width: 720px; }
.cr-ch-week { display: flex; gap: 14px; align-items: flex-start; padding: 12px 4px; border-top: 1px solid rgba(0,0,0,0.08); }
.cr-ch-week--future { opacity: 0.7; }
.cr-ch-week--now { background: rgba(0,0,0,0.025); border-radius: 8px; }
.cr-ch-check { width: 26px; height: 26px; flex: 0 0 26px; border-radius: 50%; border: 2px solid rgba(0,0,0,0.25); background: #fff; color: #fff; display: grid; place-items: center; cursor: pointer; padding: 0; }
.cr-ch-check:disabled { cursor: not-allowed; opacity: 0.5; }
.cr-ch-week.done .cr-ch-check { background: #1a7f3c; border-color: #1a7f3c; }
.cr-ch-week-text { display: flex; flex-direction: column; gap: 2px; font-size: 14px; }
.cr-ch-week-label { font-size: 11px; font-weight: 800; letter-spacing: 0.5px; text-transform: uppercase; color: var(--text-mid, #4b5058); }
.cr-q-tools { display: flex; gap: 14px; align-items: center; margin-top: 10px; font-size: 12px; }
.cr-q-public { font-weight: 700; color: var(--brand-primary, #16181d); }
.cr-q-flag { background: none; border: none; padding: 0; font: inherit; font-size: 11.5px; color: var(--text-mid, #4b5058); cursor: pointer; text-decoration: underline; }
.cr-q-reply-head .cr-q-flag { margin-left: 8px; }
/* Public solved pages */
.cpub-page { max-width: 820px; margin: 0 auto; padding: 24px 20px 60px; }
.cpub-card { border: 1px solid rgba(0,0,0,0.1); border-radius: 12px; padding: 24px; }
.cpub-crumbs { font-size: 13px; margin-bottom: 14px; color: var(--text-mid, #4b5058); }
.cpub-crumbs a { color: var(--brand-primary, #16181d); font-weight: 700; }
.cpub-thread h1 { font-size: 28px; line-height: 1.15; margin: 6px 0 12px; text-wrap: balance; }
.cpub-kicker { display: inline-block; font-size: 11px; font-weight: 800; letter-spacing: 0.8px; text-transform: uppercase; color: var(--text-mid, #4b5058); }
.cpub-kicker--answer { color: #1a7f3c; }
.cpub-body { font-size: 16px; line-height: 1.6; max-width: 65ch; }
.cpub-meta { font-size: 13px; color: var(--text-mid, #4b5058); margin: 10px 0 24px; }
.cpub-answer { border-left: 3px solid #1a7f3c; background: rgba(26,127,60,0.05); border-radius: 0 10px 10px 0; padding: 16px 18px; margin: 0 0 24px; }
.cpub-answer-by { font-weight: 700; margin: 4px 0 8px; }
.cpub-cta { border-top: 1px solid rgba(0,0,0,0.1); padding-top: 20px; display: flex; flex-wrap: wrap; gap: 10px 12px; align-items: center; }
.cpub-cta p { flex-basis: 100%; margin: 0 0 4px; font-size: 15px; max-width: 65ch; }
.cpub-cta--index { margin-top: 30px; }
.cpub-list { display: flex; flex-direction: column; }
.cpub-row { display: flex; flex-direction: column; gap: 4px; padding: 14px 4px; border-top: 1px solid rgba(0,0,0,0.08); color: inherit; text-decoration: none; }
.cpub-row:hover { background: rgba(0,0,0,0.025); }
.cpub-row-title { font-weight: 700; font-size: 16px; }
.cpub-row-body { font-size: 14px; color: var(--text-mid, #4b5058); }
.cpub-row-meta { font-size: 12px; color: var(--text-mid, #4b5058); }

/* Admin community moderation queue */
.mod-item { border: 1px solid rgba(0,0,0,0.1); border-radius: 10px; padding: 14px 16px; margin-bottom: 12px; }
.mod-item--hidden { background: rgba(0,0,0,0.03); }
.mod-item-head { display: flex; flex-wrap: wrap; gap: 8px 10px; align-items: center; }
.mod-type { font-size: 11px; font-weight: 800; letter-spacing: 0.5px; text-transform: uppercase; color: var(--text-mid, #4b5058); }
.mod-body { margin: 10px 0 4px; font-size: 14px; white-space: pre-wrap; }
.mod-reasons { margin-bottom: 6px; }
.mod-delete { margin-left: auto; color: #b42318; }

/* Coach profile + notifications + community search (2026-09-05) */
.cr-name { color: inherit; font-weight: 700; text-decoration: none; }
.cr-name:hover { text-decoration: underline; }
.cr-community-search { width: 100%; padding: 9px 12px; border: 1px solid rgba(0,0,0,0.16); border-radius: 8px; font: inherit; font-size: 14px; margin: 0 0 10px; }
.cprof-page { max-width: 820px; }
.cprof-hero { display: flex; gap: 18px; align-items: flex-start; margin: 14px 0 22px; }
.cprof-avatar { width: 72px; height: 72px; border-radius: 50%; object-fit: cover; flex: 0 0 72px; }
.cprof-avatar--initial { display: grid; place-items: center; background: var(--brand-primary, #16181d); color: #fff; font-size: 28px; font-weight: 800; }
.cprof-hero-text { flex: 1; min-width: 0; }
.cprof-hero-text h1 { margin: 0 0 2px; font-size: 26px; }
.cprof-level { margin: 8px 0 6px; font-size: 14px; }
.cprof-hero-text .cr-card-progress { max-width: 320px; }
.cprof-streak { margin-top: 8px; font-size: 13px; color: var(--text-mid, #4b5058); }
.cprof-stats { display: grid; grid-template-columns: repeat(auto-fit, minmax(140px, 1fr)); gap: 0; border-top: 1px solid rgba(0,0,0,0.12); border-bottom: 1px solid rgba(0,0,0,0.12); margin-bottom: 24px; }
.cprof-stat { padding: 14px 12px; border-right: 1px solid rgba(0,0,0,0.08); }
.cprof-stat:last-child { border-right: none; }
.cprof-stat-n { display: block; font-size: 24px; font-weight: 800; font-variant-numeric: tabular-nums; }
.cprof-stat-l { display: block; font-size: 12px; color: var(--text-mid, #4b5058); }
.cprof-list { display: flex; flex-direction: column; margin-bottom: 20px; }
.cprof-link { padding: 10px 4px; border-top: 1px solid rgba(0,0,0,0.08); color: inherit; text-decoration: none; font-weight: 600; }
.cprof-link:hover { background: rgba(0,0,0,0.025); }
.cprof-link .sub { font-weight: 400; margin-left: 6px; }
.cprof-since { margin-top: 10px; font-size: 12px; color: var(--text-mid, #4b5058); }
.notif-block { margin-bottom: 28px; }
#notif-list { display: flex; flex-direction: column; }
.notif-row { display: flex; gap: 12px; align-items: flex-start; padding: 12px 6px; border-top: 1px solid rgba(0,0,0,0.08); color: inherit; text-decoration: none; }
.notif-row:hover { background: rgba(0,0,0,0.025); }
.notif-row.unread .notif-title { font-weight: 800; }
.notif-kind { width: 8px; height: 8px; border-radius: 50%; margin-top: 7px; background: rgba(0,0,0,0.18); flex: 0 0 8px; }
.notif-row.unread .notif-kind { background: var(--brand-primary, #16181d); }
.notif-main { display: flex; flex-direction: column; gap: 2px; flex: 1; min-width: 0; }
.notif-title { font-size: 14px; }
.notif-body { font-size: 13px; color: var(--text-mid, #4b5058); }
.notif-age { font-size: 12px; color: var(--text-mid, #4b5058); white-space: nowrap; }

/* Course cover images (2026-09-06) */
.cr-card--cover { padding-top: 0 !important; overflow: hidden; }
.cr-card-cover { display: block; width: calc(100% + 2px); margin: -1px -1px 12px; aspect-ratio: 16 / 9; object-fit: cover; border-radius: 12px 12px 0 0; background: #111; }

/* Rich lesson bodies (2026-09-06): headings with a brand rule, numbered
   steps as circles, checked bullets, callouts, inline images. */
.cr-body--rich { font-size: 16px; line-height: 1.65; max-width: 68ch; }
.cr-body--rich > :first-child { margin-top: 0; }
.cr-body--rich p { margin: 0 0 14px; }
.cr-body--rich h3 { font-size: 20px; line-height: 1.2; margin: 28px 0 10px; padding-left: 14px; border-left: 4px solid var(--brand-primary, #16181d); text-wrap: balance; }
.cr-body--rich h4 { font-size: 12px; letter-spacing: 0.9px; text-transform: uppercase; color: var(--brand-primary, #16181d); margin: 22px 0 8px; }
.cr-body--rich ul, .cr-body--rich ol { margin: 0 0 16px; padding: 0; list-style: none; }
.cr-body--rich li { position: relative; padding: 8px 0 8px 40px; border-top: 1px solid rgba(0, 0, 0, 0.08); }
.cr-body--rich li:first-child { border-top: none; }
.cr-body--rich ol { counter-reset: step; }
.cr-body--rich ol > li::before {
  counter-increment: step; content: counter(step);
  position: absolute; left: 0; top: 7px; width: 26px; height: 26px; border-radius: 50%;
  background: var(--brand-primary, #16181d); color: #fff; font-size: 12px; font-weight: 800;
  display: grid; place-items: center;
}
.cr-body--rich ul > li::before {
  content: ''; position: absolute; left: 9px; top: 17px; width: 8px; height: 8px; border-radius: 2px;
  background: var(--brand-primary, #16181d);
}
/* Attached resources (worksheets / handouts): document icon, whole row is the link. */
.cr-body--rich ul[data-kind="resources"] > li::before {
  left: 4px; top: 10px; width: 18px; height: 20px; border-radius: 0; background: none;
  border: 2px solid var(--brand-primary, #16181d); border-radius: 3px;
  background-image: linear-gradient(var(--brand-primary, #16181d), var(--brand-primary, #16181d)), linear-gradient(var(--brand-primary, #16181d), var(--brand-primary, #16181d));
  background-size: 8px 2px, 8px 2px; background-position: 3px 7px, 3px 11px; background-repeat: no-repeat;
}
.cr-body--rich ul[data-kind="resources"] > li { padding-left: 34px; }
.cr-body--rich ul[data-kind="resources"] a { text-decoration: none; }
.cr-body--rich ul[data-kind="resources"] a:hover { text-decoration: underline; }
/* Linked resource files (self-hosted handouts): a file row, not a bullet */
.cr-body--rich ul[data-kind="resources"] > li:has(> a) { padding-left: 0; border-top: none; padding-top: 4px; padding-bottom: 4px; }
.cr-body--rich ul[data-kind="resources"] > li:has(> a)::before { display: none; }
.cr-body--rich ul[data-kind="resources"] > li > a { display: flex; align-items: center; gap: 12px; padding: 10px 14px 10px 10px; border: 1px solid rgba(0, 0, 0, 0.14); border-radius: 10px; background: #fff; color: #16181d; font-weight: 700; text-decoration: none; transition: border-color .15s, background .15s; }
.cr-body--rich ul[data-kind="resources"] > li > a:hover { text-decoration: none; border-color: var(--brand-primary, #16181d); background: rgba(0, 0, 0, 0.02); }
.cr-body--rich ul[data-kind="resources"] > li > a::before { content: "FILE"; flex: none; font-size: 10px; font-weight: 800; letter-spacing: .08em; line-height: 1; padding: 6px 7px; border-radius: 5px; background: var(--brand-primary, #16181d); color: #fff; }
.cr-body--rich ul[data-kind="resources"] > li > a[href$=".pdf" i]::before { content: "PDF"; }
.cr-body--rich ul[data-kind="resources"] > li > a[href$=".docx" i]::before, .cr-body--rich ul[data-kind="resources"] > li > a[href$=".doc" i]::before { content: "DOC"; }
.cr-body--rich ul[data-kind="resources"] > li > a[href$=".xlsx" i]::before { content: "XLS"; }
.cr-body--rich ul[data-kind="resources"] > li > a[href$=".pptx" i]::before { content: "PPT"; }
.cr-body--rich ul[data-kind="resources"] > li > a::after { content: ""; flex: none; margin-left: auto; width: 16px; height: 16px; background: currentColor; -webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2.4' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M12 4v11'/%3E%3Cpath d='m7 10 5 5 5-5'/%3E%3Cpath d='M5 20h14'/%3E%3C/svg%3E") center / contain no-repeat; mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2.4' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M12 4v11'/%3E%3Cpath d='m7 10 5 5 5-5'/%3E%3Cpath d='M5 20h14'/%3E%3C/svg%3E") center / contain no-repeat; }
.cr-body--rich li ul, .cr-body--rich li ol { margin: 6px 0 0; }
.cr-body--rich li li { border-top: none; padding: 4px 0 4px 30px; }
.cr-body--rich strong { font-weight: 800; }
.cr-body--rich a { color: var(--brand-primary, #16181d); font-weight: 600; text-decoration: underline; text-underline-offset: 2px; }
.cr-body--rich figure { margin: 18px 0; }
.cr-body--rich img { display: block; max-width: 100%; height: auto; border-radius: 10px; border: 1px solid rgba(0, 0, 0, 0.08); }
.cr-body--rich blockquote { margin: 18px 0; padding: 14px 18px; border-left: 4px solid var(--brand-primary, #16181d); background: rgba(0, 0, 0, 0.03); border-radius: 0 10px 10px 0; }
.cr-body--rich blockquote p:last-child { margin-bottom: 0; }
.cr-body--rich hr { border: none; border-top: 1px solid rgba(0, 0, 0, 0.12); margin: 24px 0; }
.cr-video-placeholder { display: flex; flex-direction: column; gap: 8px; align-items: flex-start; padding: 22px; margin-bottom: 18px; border: 1px dashed rgba(0, 0, 0, 0.25); border-radius: 12px; background: rgba(0, 0, 0, 0.02); font-size: 14px; }
.cr-video-placeholder strong { font-size: 16px; }

/* ================= Classroom (2026-09-03) ======================= */
.cr-loading { color: #4a5058; padding: 30px 0; }
.cr-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
  gap: 16px;
  margin-top: 6px;
}
.cr-card {
  text-align: left;
  background: #fff;
  border: 1px solid var(--border-soft, #e2e4e8);
  border-radius: 14px;
  padding: 18px 18px 16px;
  cursor: pointer;
  font-family: inherit;
  color: var(--text, #16181d);
  display: flex;
  flex-direction: column;
  gap: 7px;
}
.cr-card:hover { border-color: var(--brand-primary, #d4302b); }
.cr-card-top { display: flex; align-items: center; gap: 8px; }
.cr-card-avatar { width: 26px; height: 26px; border-radius: 999px; object-fit: cover; }
.cr-card-pro {
  font-size: 11px; font-weight: 800; letter-spacing: .1em;
  text-transform: uppercase; color: var(--brand-primary, #d4302b);
}
.cr-draft-pill {
  font-size: 10px; font-weight: 800; letter-spacing: .1em;
  background: #4a5058; color: #fff; border-radius: 999px; padding: 2px 8px;
}
.cr-card-title {
  font-family: 'acumin-pro-semi-condensed', 'Anton', Impact, system-ui, sans-serif;
  font-size: 22px; font-weight: 800; line-height: 1.08; text-transform: uppercase;
}
.cr-card-sub { font-size: 13.5px; color: #4a5058; }
.cr-card-meta { font-size: 12.5px; font-weight: 600; color: #4a5058; }
.cr-card-progress {
  display: block; height: 5px; border-radius: 999px;
  background: var(--border-soft, #e6e8ec); overflow: hidden; margin-top: 3px;
}
.cr-card-progress-bar { display: block; height: 100%; background: var(--brand-primary, #d4302b); }
.cr-card-progress-label { font-size: 11.5px; font-weight: 700; color: #4a5058; }

.cr-back { margin-bottom: 10px; }
.cr-course-hero {
  display: flex; flex-wrap: wrap; gap: 18px; justify-content: space-between;
  background: #14171c; color: #fff; border-radius: 16px; padding: 26px 26px 22px;
  margin-bottom: 18px;
}
.cr-course-hero h1 {
  margin: 0 0 4px;
  font-family: 'acumin-pro-semi-condensed', 'Anton', Impact, system-ui, sans-serif;
  font-size: 34px; text-transform: uppercase; line-height: 1.05;
}
.cr-hero-sub { margin: 0 0 10px; color: rgba(255,255,255,.8); font-size: 15px; }
.cr-hero-pro { display: flex; align-items: center; gap: 9px; font-size: 13.5px; color: rgba(255,255,255,.85); }
.cr-hero-pro img { width: 34px; height: 34px; border-radius: 999px; object-fit: cover; border: 2px solid rgba(255,255,255,.8); }
.cr-hero-desc { margin: 12px 0 0; max-width: 62ch; font-size: 14px; line-height: 1.55; color: rgba(255,255,255,.75); }
.cr-hero-progress { display: flex; flex-direction: column; gap: 6px; min-width: 160px; justify-content: center; }
.cr-hero-progress-num { font-size: 30px; font-weight: 800; }
.cr-hero-progress .cr-card-progress { background: rgba(255,255,255,.18); }
.cr-hero-progress .cr-card-progress-label { color: rgba(255,255,255,.7); }

.cr-course-layout { display: grid; grid-template-columns: 300px 1fr; gap: 20px; align-items: start; }
@media (max-width: 900px) { .cr-course-layout { grid-template-columns: 1fr; } }
.cr-lessons { display: flex; flex-direction: column; gap: 6px; }
.cr-lesson {
  display: flex; align-items: center; gap: 10px;
  background: #fff; border: 1px solid var(--border-soft, #e2e4e8);
  border-radius: 10px; padding: 10px 12px; cursor: pointer;
  font-family: inherit; text-align: left; color: var(--text, #16181d);
}
.cr-lesson.active { border-color: var(--brand-primary, #d4302b); }
.cr-lesson-check {
  flex: none; width: 22px; height: 22px; border-radius: 999px;
  display: inline-flex; align-items: center; justify-content: center;
  border: 1.5px solid var(--border, #c9cdd3); font-size: 11px; font-weight: 800; color: #4a5058;
}
.cr-lesson-check.done { background: var(--brand-primary, #d4302b); border-color: var(--brand-primary, #d4302b); color: #fff; }
.cr-lesson-title { font-size: 13.5px; font-weight: 600; line-height: 1.25; }
.cr-lesson-mins { margin-left: auto; font-size: 11.5px; color: #4a5058; font-weight: 700; }

.cr-player { background: #fff; border: 1px solid var(--border-soft, #e2e4e8); border-radius: 14px; padding: 20px 22px; }
.cr-video { position: relative; padding-top: 56.25%; border-radius: 10px; overflow: hidden; background: #000; margin-bottom: 16px; }
.cr-video iframe { position: absolute; inset: 0; width: 100%; height: 100%; border: 0; }
.cr-lesson-heading { margin: 0 0 8px; font-size: 20px; }
.cr-body { font-size: 15px; line-height: 1.6; }
.cr-player-actions { display: flex; flex-wrap: wrap; gap: 10px; margin-top: 18px; }

/* Admin courses */
.admin-courses-layout { display: grid; grid-template-columns: 1fr 460px; gap: 20px; align-items: start; }
@media (max-width: 1000px) { .admin-courses-layout { grid-template-columns: 1fr; } }
.crs-lessons-head { margin: 20px 0 8px; }
.crs-lesson-editor {
  border: 1px solid var(--border-soft, #e2e4e8); border-radius: 10px;
  padding: 10px; margin-bottom: 10px; display: flex; flex-direction: column; gap: 7px;
}
.crs-lesson-editor input, .crs-lesson-editor textarea {
  border: 1px solid var(--border, #d0d4d9); border-radius: 7px;
  padding: 7px 9px; font-size: 13.5px; font-family: inherit;
}
.crs-lesson-editor-row { display: flex; gap: 7px; }
.crs-l-pos { width: 52px; }
.crs-l-title { flex: 1; }
.crs-l-mins { width: 64px; }
.crs-lesson-editor-actions { display: flex; gap: 8px; }

/* Classroom gating */
.cr-lock-pill {
  display: inline-flex; align-items: center; gap: 4px;
  font-size: 10px; font-weight: 800; letter-spacing: .08em; text-transform: uppercase;
  border: 1px solid var(--border, #c9cdd3); color: #4a5058;
  border-radius: 999px; padding: 2px 8px;
}
.cr-upgrade { text-align: center; padding: 40px 24px; }
.cr-upgrade svg { width: 30px; height: 30px; color: var(--brand-primary, #d4302b); }
.cr-upgrade h2 { margin: 10px 0 8px; font-size: 21px; }
.cr-upgrade p { margin: 0 auto 18px; max-width: 46ch; font-size: 14.5px; line-height: 1.55; color: #4a5058; }

/* Classroom quizzes */
.cr-quiz-tag {
  font-size: 9.5px; font-weight: 800; letter-spacing: .1em;
  color: var(--brand-primary, #d4302b); border: 1px solid currentColor;
  border-radius: 4px; padding: 1px 5px; vertical-align: 1px;
}
.cr-quiz-q { border: 1px solid var(--border-soft, #e2e4e8); border-radius: 10px; padding: 14px 16px; margin: 0 0 14px; }
.cr-quiz-q legend { font-weight: 700; font-size: 15px; padding: 0 4px; }
.cr-quiz-opt { display: flex; align-items: center; gap: 9px; padding: 7px 4px; font-size: 14.5px; cursor: pointer; }
.cr-quiz-verdict { font-size: 13px; font-weight: 700; margin-top: 6px; }
.cr-quiz-verdict.good, .cr-quiz-result.good { color: #1e7a46; }
.cr-quiz-verdict.bad, .cr-quiz-result.bad { color: var(--brand-primary, #d4302b); }
.cr-quiz-result { margin-left: 12px; font-weight: 800; }
.cr-quiz-passed { color: #1e7a46; font-weight: 700; }

/* Admin quiz editor */
.crs-quiz-q { border: 1px dashed var(--border, #c9cdd3); border-radius: 8px; padding: 9px; margin-bottom: 9px; display: flex; flex-direction: column; gap: 6px; }
.crs-q-opt { display: flex; align-items: center; gap: 7px; }
.crs-q-opt .crs-q-opttext { flex: 1; }
.crs-quiz-hint { font-size: 12px; color: #4a5058; margin: 6px 0 0; }
.crs-l-lessonfields, .crs-l-quizfields { display: flex; flex-direction: column; gap: 7px; }

/* ================= Pro Portal (flat, hairlines, no KPI cards) ===== */
.pp-adminview {
  background: #fff7e6; border: 1px solid #e8c87a; color: #7a5a00;
  border-radius: 8px; padding: 8px 14px; font-size: 13px; font-weight: 600; margin-bottom: 14px;
}
.pp-head-row { display: flex; align-items: center; gap: 14px; }
.pp-head-row h1 { margin: 0; }
.pp-avatar { width: 54px; height: 54px; border-radius: 999px; object-fit: cover; }
.pp-kpis {
  display: flex; flex-wrap: wrap;
  border-top: 1px solid var(--border-soft, #e2e4e8);
  border-bottom: 1px solid var(--border-soft, #e2e4e8);
  margin: 18px 0 6px;
}
.pp-kpi {
  flex: 1 1 120px; padding: 16px 18px;
  display: flex; flex-direction: column; gap: 2px;
}
.pp-kpi + .pp-kpi { border-left: 1px solid var(--border-soft, #e2e4e8); }
.pp-kpi-num { font-size: 28px; font-weight: 800; font-variant-numeric: tabular-nums; }
.pp-kpi-label { font-size: 12px; font-weight: 700; letter-spacing: .07em; text-transform: uppercase; color: #4a5058; }
.pp-section-title { display: flex; align-items: center; gap: 12px; margin: 26px 0 10px; font-size: 19px; }
.pp-csv { font-size: 12.5px; padding: 5px 12px; }
.tbl-wrap-plain { overflow-x: auto; }
.pp-table { border-collapse: collapse; width: 100%; font-size: 14px; }
.pp-table th {
  text-align: left; font-size: 11.5px; letter-spacing: .07em; text-transform: uppercase;
  color: #4a5058; padding: 8px 12px; border-bottom: 1px solid var(--border-soft, #e2e4e8);
}
.pp-table td { padding: 9px 12px; border-bottom: 1px solid var(--border-soft, #eef0f2); }
.pp-course { border-top: 1px solid var(--border-soft, #e2e4e8); padding: 14px 2px; }
.pp-course-head { display: flex; flex-wrap: wrap; gap: 10px; align-items: baseline; font-size: 15.5px; }
.pp-course-status { font-size: 12px; font-weight: 700; color: #4a5058; }
.pp-course-stats { font-size: 13px; color: #4a5058; margin-top: 3px; }
.pp-lessons { margin-top: 8px; }
.pp-lesson-row {
  display: flex; justify-content: space-between; gap: 12px;
  font-size: 13px; padding: 5px 0; border-bottom: 1px solid var(--border-soft, #f0f1f3);
}
.pp-qlist { margin: 6px 0 0; padding-left: 20px; font-size: 14px; }
.pp-qlist li { margin: 4px 0; }
.pp-qdate { color: #4a5058; font-size: 12px; }

/* Float the style bar + dock over the BOARD column, not the viewport:
   centered between the left tool rail and the right drawer, so neither
   bar ever runs under the drawer (tags/notes/ad panel) — Ian 2026-09-04:
   "make sure that the tags and notes are not conflicting with the
   toolbars". The sidebar-resize handle updates --sidebar-w live. */
@media (min-width: 641px) {
  body.route-drill { --dock-rail-w: 108px; --dock-side-w: var(--sidebar-w, 300px); }
  body.route-drill.tools-collapsed { --dock-rail-w: 22px; }
  body.route-drill.sidebar-collapsed { --dock-side-w: 0px; }
  body.route-drill .drill-dock,
  body.route-drill .line-picker {
    left: calc(50% + (var(--dock-rail-w) - var(--dock-side-w)) / 2);
  }
}

/* Bars hug the board (Ian 2026-09-04: "tighten") — fitCanvas measures the
   slack under the rink into --bars-lift; draw mode only, and never in
   notes-below (there the column scrolls under viewport-anchored bars). */
@media (min-width: 641px) {
  body.route-drill.drill-mode-draw:not(.drill-notes-below) .drill-dock {
    bottom: calc(20px + var(--bars-lift, 0px));
  }
  body.route-drill.drill-mode-draw:not(.drill-notes-below) .line-picker {
    bottom: calc(86px + var(--dock-ctx-lift, 0px) + var(--bars-lift, 0px));
  }
}

/* Course hero cover background — at the END so it beats the classroom
   block's `background` shorthand (2026-09-06). */
.cr-course-hero.cr-course-hero--cover {
  /* Solid where the copy sits (left), opening up to the art on the right. */
  background-image: linear-gradient(100deg, rgba(17, 17, 20, 0.97) 0%, rgba(17, 17, 20, 0.92) 42%, rgba(17, 17, 20, 0.55) 100%), var(--cover, none);
  background-size: cover;
  background-position: center right;
  background-repeat: no-repeat;
}
@media (max-width: 760px) {
  .cr-course-hero.cr-course-hero--cover { background-image: linear-gradient(rgba(17, 17, 20, 0.9), rgba(17, 17, 20, 0.94)), var(--cover, none); }
}

/* Classroom catalog covers: bleed edge-to-edge over the card's 18px side padding + 1px border (Ian 2026-09-06). */
.cr-card.cr-card--cover { padding-top: 0 !important; }
.cr-card.cr-card--cover .cr-card-cover { width: calc(100% + 38px); max-width: none; margin: -1px -19px 12px; border-radius: 13px 13px 0 0; }

/* ---- Top banner: rotating pro offers (Ian 2026-09-06) --------------------
   Sits INSIDE the page under the heading + description (classroom first).
   One offer visible; the next scrolls up into view (translateY) while the
   current one scrolls out. Flat brand-primary for the kicker chip + CTA
   per docs/STYLE.md. Row = track | dots | close as flex siblings so the
   dots never sit over the CTA. */
.pc-topbanner { background: #fff; border: 1px solid var(--border-soft, #e2e4e8); border-radius: 12px; margin: 0 0 18px; }
.pc-tb { display: flex; align-items: center; gap: 12px; height: 60px; padding: 0 8px 0 14px; }
.pc-tb-track { position: relative; flex: 1 1 auto; min-width: 0; height: 100%; overflow: hidden; }
.pc-tb-item { position: absolute; inset: 0; display: flex; align-items: center; gap: 14px; width: 100%; padding: 0; margin: 0; border: 0; background: none; font: inherit; color: var(--text, #16181d); text-align: left; text-decoration: none; cursor: pointer;
  opacity: 0; transform: translateY(100%); pointer-events: none; transition: transform .55s cubic-bezier(.2,.7,.2,1), opacity .4s ease; }
.pc-tb-item.is-active { opacity: 1; transform: translateY(0); pointer-events: auto; }
.pc-tb-item.is-out { opacity: 0; transform: translateY(-100%); }
.pc-tb--fade .pc-tb-item { transform: none; transition: opacity .4s ease; }
.pc-tb-avatar { flex: none; width: 38px; height: 38px; border-radius: 50%; object-fit: cover; border: 2px solid var(--brand-primary, #7c5cff); box-sizing: border-box; background: #fff; }
.pc-tb-avatar--blank { background: var(--brand-primary, #7c5cff); opacity: .25; border: 0; }
.pc-tb-text { flex: 1 1 auto; min-width: 0; display: flex; align-items: baseline; gap: 10px; }
.pc-tb-kicker { flex: none; font-size: 10.5px; font-weight: 800; letter-spacing: .08em; text-transform: uppercase; color: var(--brand-primary, #7c5cff); }
.pc-tb-kicker--free { background: var(--brand-primary, #7c5cff); color: #fff; border-radius: 999px; padding: 3px 8px; letter-spacing: .06em; }
.pc-tb-title { flex: 0 1 auto; min-width: 0; max-width: 58%; font-weight: 700; font-size: 15px; color: var(--text, #16181d); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.pc-tb-sub { flex: 1 1 0; font-size: 13px; color: #4a5058; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; min-width: 0; }
.pc-tb-cta { flex: none; display: inline-flex; align-items: center; gap: 6px; background: var(--brand-primary, #7c5cff); color: #fff; font-weight: 700; font-size: 13px; border-radius: 8px; padding: 8px 12px; white-space: nowrap; transition: filter .15s; }
.pc-tb-item:hover .pc-tb-cta, .pc-tb-item:focus-visible .pc-tb-cta { filter: brightness(1.08); }
.pc-tb-item:focus-visible { outline: 2px solid var(--brand-primary, #7c5cff); outline-offset: -2px; border-radius: 8px; }
.pc-tb-dots { flex: none; display: flex; align-items: center; gap: 2px; padding-left: 6px; border-left: 1px solid var(--border-soft, #e2e4e8); height: 28px; }
.pc-tb-dot { width: 18px; height: 28px; padding: 0; border: 0; background: none; cursor: pointer; position: relative; }
.pc-tb-dot::before { content: ""; position: absolute; left: 50%; top: 50%; width: 7px; height: 7px; margin: -3.5px 0 0 -3.5px; border-radius: 50%; background: rgba(22, 24, 29, .2); transition: background .2s, transform .2s; }
.pc-tb-dot:hover::before { background: rgba(22, 24, 29, .45); }
.pc-tb-dot.is-active::before { background: var(--brand-primary, #7c5cff); transform: scale(1.25); }
.pc-tb-dot:focus-visible { outline: 2px solid var(--brand-primary, #7c5cff); outline-offset: -2px; border-radius: 6px; }
.pc-tb-close { flex: none; width: 30px; height: 30px; display: inline-flex; align-items: center; justify-content: center; border: 0; border-radius: 50%; background: none; color: #4a5058; cursor: pointer; }
.pc-tb-close:hover { background: rgba(22, 24, 29, .06); color: var(--text, #16181d); }
@media (max-width: 760px) {
  .pc-tb { height: 66px; gap: 6px; padding: 0 4px 0 10px; }
  .pc-tb-item { gap: 10px; }
  .pc-tb-text { flex-direction: column; align-items: flex-start; gap: 2px; }
  .pc-tb-sub, .pc-tb-dots { display: none; }
  .pc-tb-title { max-width: none; width: 100%; font-size: 14px; white-space: normal; display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; line-height: 1.2; }
  .pc-tb-cta { padding: 7px 10px; font-size: 12px; }
  .pc-tb-cta svg { display: none; }
  .pc-tb-avatar { width: 32px; height: 32px; }
}

/* ---- Classroom tag filter (Ian 2026-09-06) --------------------------
   Chip row between the offers band and the course grid. Flat brand-
   primary for the active chip (docs/STYLE.md); tiny pills on the cards
   that filter too. */
.cr-tags { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; margin: 0 0 18px; }
.cr-tags-label { font-size: 12px; font-weight: 700; letter-spacing: .08em; text-transform: uppercase; color: #4a5058; margin-right: 4px; }
.cr-tag { display: inline-flex; align-items: center; gap: 6px; padding: 7px 12px; border: 1px solid var(--border-soft, #e2e4e8); border-radius: 999px; background: #fff; color: var(--text, #16181d); font: inherit; font-size: 13px; font-weight: 600; cursor: pointer; transition: border-color .15s, background .15s, color .15s; }
.cr-tag:hover { border-color: var(--brand-primary, #7c5cff); }
.cr-tag.is-active { background: var(--brand-primary, #7c5cff); border-color: var(--brand-primary, #7c5cff); color: #fff; }
.cr-tag-n { font-size: 11px; font-weight: 700; color: #4a5058; background: rgba(22, 24, 29, .06); border-radius: 999px; padding: 1px 6px; }
.cr-tag.is-active .cr-tag-n { color: #fff; background: rgba(255, 255, 255, .22); }
.cr-tag:focus-visible { outline: 2px solid var(--brand-primary, #7c5cff); outline-offset: 2px; }
.cr-card-tags { display: flex; flex-wrap: wrap; gap: 5px; }
.cr-card-tag { font-size: 11px; font-weight: 600; color: #4a5058; border: 1px solid var(--border-soft, #e2e4e8); border-radius: 999px; padding: 2px 8px; background: #fff; cursor: pointer; transition: border-color .15s, color .15s; }
.cr-card-tag:hover { border-color: var(--brand-primary, #7c5cff); color: var(--brand-primary, #7c5cff); }
.cr-card-tag.is-active { background: var(--brand-primary, #7c5cff); border-color: var(--brand-primary, #7c5cff); color: #fff; }

/* Course promos on the offer cards (Ian 2026-09-06): optional sub line;
   link-kind CTA is an <a> styled like the button. */
.gl-offer-sub { display: block; max-width: 52ch; margin: -6px auto 12px; font-size: 13px; line-height: 1.4; color: #4a5058; }
a.gl-offer-cta { text-decoration: none; }

/* Band: link sponsors show their wordmark at natural shape (no circle crop). */
.pc-tb-logo { flex: none; height: 30px; width: auto; max-width: 120px; object-fit: contain; border-radius: 6px; }
@media (max-width: 760px) { .pc-tb-logo { height: 26px; max-width: 96px; } }

/* Who's-going headshot strip on a schedule row — first 5 headshots
   OVERLAPPING, then a "+X going" count. Sits under the plan chip (or the
   time). No side label. (Ian 2026-09-06) */
.sched-attending { display: inline-flex; align-items: center; gap: 9px; margin-top: 9px; padding: 2px 2px 2px 0; border: none; background: none; font: inherit; color: inherit; cursor: pointer; text-align: left; border-radius: 8px; }
.sched-attending:hover .sched-attending-count { color: var(--brand-primary, #d4302b); }
.sched-attending:focus-visible { outline: 2px solid var(--brand-primary, #d4302b); outline-offset: 2px; }
.sched-att-icon { display: inline-flex; align-items: center; color: var(--text-dim, #5a6270); }
.sched-att-icon svg { width: 20px; height: 20px; }
.sched-heads { display: flex; align-items: center; }
.sched-head-wrap { position: relative; display: inline-flex; margin-left: -10px; }
.sched-head-wrap:first-child { margin-left: 0; }
.sched-head { flex: none; width: 32px; height: 32px; border-radius: 50%; object-fit: cover; background: #e8ecf2; border: 2px solid var(--bg, #fff); box-sizing: border-box; box-shadow: 0 1px 3px rgba(0,0,0,.14); display: block; }
.sched-head--init { align-items: center; justify-content: center; font-size: 11px; font-weight: 800; color: #fff; background: var(--brand-primary, #d4302b); }
.sched-attending-count { font-size: 12.5px; font-weight: 700; color: var(--text-dim, #5a6270); white-space: nowrap; }
/* Desktop hover tooltip with the player's name (not clickable). */
@media (hover: hover) and (pointer: fine) {
  .sched-head-wrap:hover { z-index: 6; }
  .sched-head-wrap[data-name]:hover::after {
    content: attr(data-name);
    position: absolute; left: 50%; bottom: calc(100% + 8px); transform: translateX(-50%);
    padding: 4px 9px; border-radius: 7px; white-space: nowrap;
    background: var(--panel-dark, #2c3036); color: #fff;
    font-size: 11px; font-weight: 600; line-height: 1.3; letter-spacing: normal; text-transform: none;
    box-shadow: 0 4px 14px rgba(0,0,0,.2); pointer-events: none; z-index: 30;
  }
  .sched-head-wrap[data-name]:hover::before {
    content: ""; position: absolute; left: 50%; bottom: calc(100% + 3px); transform: translateX(-50%);
    border: 5px solid transparent; border-top-color: var(--panel-dark, #2c3036); pointer-events: none; z-index: 30;
  }
}

/* ===== Locked lines + line report (Ian 2026-09-06) ======================== */
.btn.btn-sm { padding: 4px 10px; font-size: 12.5px; }
.lock-list { display: flex; flex-direction: column; gap: 6px; max-height: 52vh; overflow-y: auto; }
.lock-row { display: flex; align-items: center; gap: 10px; padding: 9px 4px; border-bottom: 1px solid var(--border-soft, #eef0f3); }
.lock-row:last-child { border-bottom: none; }
.lock-row-main { flex: 1 1 auto; min-width: 0; display: flex; align-items: center; gap: 9px; }
.lock-row-type { flex: none; font-size: 9.5px; font-weight: 800; letter-spacing: .06em; text-transform: uppercase; padding: 3px 7px; border-radius: 5px; color: #fff; background: #6b7280; }
.lock-row-type.game { background: var(--brand-primary, #d4302b); }
.lock-row-type.practice { background: #2c3036; }
.lock-row-type.event { background: #0e7490; }
.lock-row-label { font-weight: 600; color: var(--text, #16181d); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.lock-row-date { flex: none; font-size: 12px; color: var(--text-dim, #5a6270); }
.lock-badge { flex: none; font-size: 10px; font-weight: 800; letter-spacing: .05em; text-transform: uppercase; color: #157347; background: rgba(34,197,94,.12); border-radius: 999px; padding: 3px 8px; }
.lock-remove { flex: none; width: 26px; height: 26px; border: none; background: none; border-radius: 6px; color: #5a6270; font-size: 18px; line-height: 1; cursor: pointer; }
.lock-remove:hover { background: rgba(0,0,0,.06); color: var(--danger, #dc2626); }

.lr-tabs { display: flex; gap: 6px; margin: 4px 0 14px; border-bottom: 1px solid var(--border-soft, #e2e4e8); }
.lr-tab { border: none; background: none; font: inherit; font-size: 13.5px; font-weight: 700; color: var(--text-dim, #5a6270); padding: 8px 4px; margin-bottom: -1px; border-bottom: 2px solid transparent; cursor: pointer; }
.lr-tab.is-on { color: var(--brand-primary, #d4302b); border-bottom-color: var(--brand-primary, #d4302b); }
.lr-note { font-size: 12.5px; color: var(--text-dim, #5a6270); margin: 0 0 14px; line-height: 1.5; }
.lr-empty { text-align: center; padding: 26px 16px; color: var(--text-dim, #5a6270); }
.lr-empty b { color: var(--text, #16181d); font-size: 15px; }
.lr-empty p { margin: 8px auto 0; max-width: 42ch; font-size: 13px; line-height: 1.5; }
.lr-unit-title { font-size: 11px; font-weight: 800; letter-spacing: .06em; text-transform: uppercase; color: var(--text-dim, #5a6270); margin: 16px 0 8px; }
.lr-table-wrap { overflow-x: auto; }
.lr-table { width: 100%; border-collapse: collapse; font-size: 13px; }
.lr-table th { text-align: left; font-size: 10.5px; font-weight: 800; letter-spacing: .04em; text-transform: uppercase; color: var(--text-dim, #5a6270); padding: 6px 8px; border-bottom: 1px solid var(--border-soft, #e2e4e8); white-space: nowrap; }
.lr-table td { padding: 8px; border-bottom: 1px solid var(--border-soft, #eef0f3); vertical-align: middle; }
.lr-table .lr-num { text-align: right; font-variant-numeric: tabular-nums; white-space: nowrap; }
.lr-table th.lr-num { text-align: right; }
.lr-rank { color: var(--text-dim, #5a6270); font-weight: 700; width: 20px; }
.lr-diff.pos { color: #157347; font-weight: 700; }
.lr-diff.neg { color: var(--danger, #dc2626); font-weight: 700; }
.lr-line { display: inline-flex; flex-wrap: wrap; align-items: center; gap: 2px; }
.lr-plr { font-weight: 600; color: var(--text, #16181d); }
.lr-plr b { font-weight: 800; color: var(--brand-primary, #d4302b); }
.lr-x { color: var(--text-dim, #9aa3ad); margin: 0 3px; }
.lr-res { font-size: 10.5px; font-weight: 800; border-radius: 5px; padding: 2px 6px; color: #fff; }
.lr-res--w { background: #157347; }
.lr-res--l { background: var(--danger, #dc2626); }
.lr-res--t { background: #6b7280; }
.lr-hist { display: flex; flex-direction: column; gap: 12px; }
.lr-hist-row { border: 1px solid var(--border-soft, #e2e4e8); border-radius: 10px; padding: 11px 13px; }
.lr-hist-head { display: flex; align-items: center; gap: 9px; flex-wrap: wrap; }
.lr-hist-label { font-weight: 700; color: var(--text, #16181d); }
.lr-hist-meta { font-size: 12px; color: var(--text-dim, #5a6270); }
.lr-hist-lines { display: flex; align-items: flex-start; gap: 8px; margin-top: 8px; flex-wrap: wrap; }
.lr-hist-tag { flex: none; font-size: 10px; font-weight: 800; color: var(--text-dim, #5a6270); background: var(--bg-soft, #f2f4f7); border-radius: 5px; padding: 3px 6px; margin-top: 1px; }
.lr-hist-lines .lr-line { border: 1px solid var(--border-soft, #e2e4e8); border-radius: 999px; padding: 3px 10px; font-size: 12px; }
