/*
  Phase components: the small set of building blocks every page uses.

    Buttons   .btn + .btn-primary | .btn-secondary | .btn-ghost | .btn-danger
              sizes .btn-sm, .btn-lg, .btn-icon (round, icon only), .btn-block (full width)
    Cards     .card (a panel), .card-raised (a panel on a panel), .card-link (tappable),
              .card-current (the one that matters now: gold outline and a soft glow)
    Icons     .icon-tile (a Lucide icon in a rounded square, tinted gold)
    Lists     .list (a panel of rows) with .list-row (one row; <a> rows are tappable)
    Inputs    .input (text, select, textarea), .label, .pill (the big kg/reps boxes),
              .stepper (− value + around a pill)
    Chips     .chip, .chip-active, .chip-accent, .chip-warn, .chip-danger
    Type      .t-display (big numbers), .t-title (28/800), .t-stat (30/800 counts), .t-heading (16/700),
              .t-label (small uppercase, spaced), .t-eyebrow (the same in gold), .num
    Feedback  .toast, .skeleton, .empty (empty states)
    Nav       .tabbar (phones), .sidebar (laptops), .nav-item

  Colours come from the CSS variables set in base.html (accounts/branding.py),
  so everything follows dark/light mode and team colours.

  The layer order below matches Tailwind's, so a Tailwind class on the same
  element (e.g. "btn btn-primary w-full") always wins over these defaults.
*/
@layer theme, base, components, utilities;

/* ---------- Nothing is ever wider than the screen ----------
   In the base layer, so any Tailwind class (e.g. min-w-24) still wins. Wide things
   (tables, chip rows) scroll sideways inside their own overflow-x-auto box instead.
   Checked on every page at 360px and 390px: training/tests/test_mobile_width.py */
@layer base {
  .page { overflow-x: clip; }                                       /* the wrapper round the header, page and footer */
  main { overflow-wrap: break-word; }                               /* long names and links wrap */
  main :where(.flex, .inline-flex, .grid) > * { min-width: 0; }    /* flex/grid items can shrink below their text */
}

@layer components {
  .icon { flex-shrink: 0; }  /* icons keep their size next to long labels */
  /* ---------- Type ---------- */
  .t-display { font-size: 2.5rem; line-height: 1; font-weight: 800; letter-spacing: -0.03em; }
  .t-title { font-size: 1.75rem; line-height: 1.15; font-weight: 800; letter-spacing: -0.02em; }
  .t-stat { font-size: 1.875rem; line-height: 1; font-weight: 800; letter-spacing: -0.02em; font-variant-numeric: tabular-nums; }
  .t-heading { font-size: 1rem; line-height: 1.35; font-weight: 700; letter-spacing: -0.005em; }
  .t-label { font-size: 0.6875rem; line-height: 1rem; font-weight: 800; letter-spacing: 0.16em; text-transform: uppercase; color: var(--muted); }
  .t-eyebrow { font-size: 0.6875rem; line-height: 1rem; font-weight: 800; letter-spacing: 0.16em; text-transform: uppercase; color: var(--brand-ink); }
  .num { font-variant-numeric: tabular-nums; font-weight: 800; letter-spacing: -0.02em; }
  @media (min-width: 640px) { .t-display { font-size: 3rem; } }

  /* ---------- Buttons ---------- */
  .btn {
    display: inline-flex; align-items: center; justify-content: center; gap: 0.5rem;
    min-height: 3rem; padding: 0 1.25rem; border-radius: 0.875rem;
    font-weight: 700; font-size: 1rem; line-height: 1.2; text-align: center; white-space: nowrap;
    text-decoration: none; cursor: pointer; user-select: none; -webkit-tap-highlight-color: transparent;
    transition: transform 150ms ease, background-color 150ms ease, color 150ms ease, opacity 150ms ease, box-shadow 150ms ease;
  }
  .btn:active { transform: scale(0.97); }
  .btn:disabled, .btn[aria-disabled="true"] { opacity: 0.45; cursor: not-allowed; transform: none; }
  .btn-primary { background: var(--brand); color: var(--on-brand); }
  .btn-primary:hover { box-shadow: 0 0 0 4px color-mix(in srgb, var(--brand) 22%, transparent); }
  .btn-secondary { background: var(--raised); color: var(--ink); box-shadow: inset 0 0 0 1px var(--line); }
  .btn-secondary:hover { background: color-mix(in srgb, var(--raised) 80%, var(--ink)); }
  .btn-ghost { background: transparent; color: var(--brand-ink); }
  .btn-ghost:hover { background: var(--raised); }
  .btn-danger { background: color-mix(in srgb, var(--danger) 14%, transparent); color: var(--danger); }
  .btn-danger:hover { background: color-mix(in srgb, var(--danger) 22%, transparent); }
  .btn-sm { min-height: 2.75rem; padding: 0 1rem; font-size: 0.9375rem; }
  .btn-lg { min-height: 3.5rem; padding: 0 1.75rem; font-size: 1.0625rem; }
  .btn-icon { width: 2.75rem; min-height: 2.75rem; padding: 0; flex-shrink: 0; border-radius: 999px; }
  .btn-block { display: flex; width: 100%; }

  /* ---------- Cards and lists ---------- */
  /* Panels: a hairline border and no shadow; told apart from the page by colour */
  .card { background: var(--card); border: 1px solid var(--line); border-radius: 1.0625rem; padding: 1rem; }
  .card-raised { background: var(--raised); border: 1px solid var(--line); border-radius: 0.875rem; padding: 0.875rem 1rem; }
  /* What matters right now (the next session, the exercise being done): gold outline, soft gold glow */
  /* One continuous border all the way round (it follows the corners), and a very faint glow (none in light mode) */
  .card-current { border: 1.5px solid var(--accent); box-shadow: 0 4px 16px color-mix(in srgb, var(--accent) 9%, transparent); }
  :root[data-theme="light"] .card-current { box-shadow: none; }
  .icon-tile {
    display: inline-flex; align-items: center; justify-content: center; flex-shrink: 0;
    width: 2.5rem; height: 2.5rem; border-radius: 0.75rem;
    background: color-mix(in srgb, var(--accent) 12%, transparent); color: var(--brand-ink);
  }
  .card-link { display: block; transition: transform 150ms ease, background-color 150ms ease; -webkit-tap-highlight-color: transparent; }
  .card-link:hover { background: color-mix(in srgb, var(--card) 88%, var(--ink)); }
  .card-link:active { transform: scale(0.985); }
  @media (min-width: 640px) { .card { padding: 1.25rem; } }

  .list { background: var(--card); border: 1px solid var(--line); border-radius: 1.0625rem; overflow: hidden; }
  .list > * + * { border-top: 1px solid var(--line); }
  .list-row { display: flex; align-items: center; gap: 0.875rem; min-height: 3.5rem; padding: 0.75rem 1rem; }
  a.list-row, button.list-row { width: 100%; text-align: left; transition: background-color 150ms ease; -webkit-tap-highlight-color: transparent; }
  a.list-row:hover, button.list-row:hover { background: color-mix(in srgb, var(--card) 88%, var(--ink)); }
  a.list-row:active { background: var(--raised); }
  /* Stand-in for a team badge, shown only if the badge can't load (templates/partials/team_badge.html) */
  [data-badge-fallback][hidden] { display: none !important; }
  .list-icon {
    display: inline-flex; align-items: center; justify-content: center; flex-shrink: 0;
    width: 2.5rem; height: 2.5rem; border-radius: 0.75rem;
    background: color-mix(in srgb, var(--accent) 12%, transparent); color: var(--brand-ink);
  }

  /* ---------- Inputs ---------- */
  .label { display: block; margin-bottom: 0.375rem; font-size: 0.875rem; font-weight: 600; color: var(--muted); }
  .input {
    display: block; width: 100%; min-height: 3rem; padding: 0 1rem;
    border-radius: 0.875rem; border: 1px solid var(--line); background: var(--raised); color: var(--ink);
    font-size: 1rem; transition: border-color 150ms ease, box-shadow 150ms ease, background-color 150ms ease;
  }
  textarea.input { padding: 0.75rem 1rem; line-height: 1.5; }
  select.input { padding-right: 2.5rem; appearance: none;
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23888' stroke-width='2' stroke-linecap='round'%3E%3Cpath d='m6 9 6 6 6-6'/%3E%3C/svg%3E");
    background-repeat: no-repeat; background-position: right 0.875rem center; background-size: 1.125rem; }
  .input::placeholder, .pill::placeholder { color: color-mix(in srgb, var(--muted) 75%, transparent); }
  .input:hover { border-color: var(--line-strong); }
  .input:focus, .pill:focus, .pill:focus-within {
    outline: none; border-color: var(--accent);
    box-shadow: 0 0 0 3px color-mix(in srgb, var(--accent) 28%, transparent);
  }
  .input[aria-invalid="true"], .input.is-invalid, .pill.is-invalid { border-color: var(--danger); }

  /* The big kg and reps boxes on the Train screen */
  .pill {
    width: 100%; min-width: 0; height: 3.5rem; border-radius: 0.875rem; border: 1px solid transparent;
    background: var(--raised); color: var(--ink); text-align: center;
    font-size: 1.125rem; font-weight: 800; font-variant-numeric: tabular-nums; letter-spacing: -0.02em;
    transition: border-color 150ms ease, box-shadow 150ms ease;
  }
  /* − value + : the input sits between two round buttons, all in one pill */
  .stepper {
    display: flex; align-items: center; height: 3.5rem; min-width: 0; border-radius: 0.875rem;
    background: var(--raised); border: 1px solid transparent; transition: border-color 150ms ease, box-shadow 150ms ease;
  }
  .stepper:focus-within { border-color: var(--accent); box-shadow: 0 0 0 3px color-mix(in srgb, var(--accent) 28%, transparent); }
  @media (min-width: 640px) { .pill { font-size: 1.25rem; } }
  .stepper .pill { background: transparent; border: 0; box-shadow: none; padding: 0; height: 100%; }
  .stepper .pill:focus { box-shadow: none; }
  .stepper button {
    display: inline-flex; align-items: center; justify-content: center; flex-shrink: 0;
    width: 1.75rem; height: 2.75rem; min-height: 0; margin: 0 0.125rem; border-radius: 999px;
    color: var(--muted); transition: background-color 150ms ease, transform 150ms ease, color 150ms ease;
    -webkit-tap-highlight-color: transparent;
  }
  .stepper button:hover { background: var(--card); color: var(--ink); }
  @media (min-width: 640px) { .stepper button { width: 2.75rem; height: 2.75rem; margin: 0 0.25rem; } }
  .stepper button:active { transform: scale(0.88); }

  /* Choice boxes (radio buttons and tick boxes made into big tappable tiles) */
  .choice {
    display: flex; align-items: center; gap: 0.75rem; min-height: 3.25rem; padding: 0.75rem 1rem;
    border-radius: 0.875rem; background: var(--raised); border: 1.5px solid transparent; font-weight: 600; cursor: pointer;
    transition: border-color 150ms ease, background-color 150ms ease;
  }
  .choice:has(input:checked) { border-color: var(--accent); background: color-mix(in srgb, var(--accent) 12%, var(--raised)); }
  .choice input { width: 1.25rem; height: 1.25rem; accent-color: var(--brand); flex-shrink: 0; }

  /* ---------- Chips ---------- */
  .chip {
    display: inline-flex; align-items: center; gap: 0.375rem; min-height: 1.75rem; padding: 0.125rem 0.75rem;
    border-radius: 999px; background: var(--raised); color: var(--ink);
    font-size: 0.8125rem; font-weight: 700; line-height: 1.2; white-space: nowrap;
  }
  a.chip, button.chip { min-height: 2.75rem; padding: 0 1rem; font-size: 0.9375rem; transition: background-color 150ms ease, color 150ms ease; }
  .chip-active { background: var(--brand); color: var(--on-brand); }
  .chip-accent { background: color-mix(in srgb, var(--accent) 18%, transparent); color: var(--brand-ink); }
  .chip-warn { background: color-mix(in srgb, #f59e0b 20%, transparent); color: var(--warn-ink); }
  .chip-danger { background: color-mix(in srgb, var(--danger) 16%, transparent); color: var(--danger); }

  /* ---------- Navigation ---------- */
  .tabbar {
    position: fixed; inset: auto 0 0 0; z-index: 30; display: flex; justify-content: space-around;
    padding: 0.375rem 0.5rem calc(0.375rem + env(safe-area-inset-bottom, 0px));
    background: color-mix(in srgb, var(--surface) 92%, transparent);
    backdrop-filter: saturate(1.4) blur(16px); -webkit-backdrop-filter: saturate(1.4) blur(16px);
    border-top: 1px solid var(--line);
  }
  .tabbar .nav-item {
    position: relative; flex: 1; display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 0.125rem;
    min-height: 3.25rem; max-width: 6rem; border-radius: 0.875rem;
    font-size: 0.6875rem; font-weight: 700; color: var(--muted); transition: color 150ms ease, transform 150ms ease;
    -webkit-tap-highlight-color: transparent;
  }
  .tabbar .nav-item:active { transform: scale(0.94); }
  .tabbar .nav-item .icon { width: 1.5rem; height: 1.5rem; transition: transform 200ms ease; }
  .tabbar .nav-item[aria-current="page"] { color: var(--brand-ink); }  /* text: brand-ink is 7:1; --accent is only for marks (3:1) */
  .tabbar .nav-item[aria-current="page"] .icon { transform: translateY(-1px); stroke-width: 2.4; }


  .sidebar { background: var(--surface); border-right: 1px solid var(--line); }
  .sidebar .nav-item {
    display: flex; align-items: center; gap: 0.75rem; min-height: 2.75rem; padding: 0 0.875rem; border-radius: 0.75rem;
    font-weight: 600; color: var(--muted); transition: background-color 150ms ease, color 150ms ease;
  }
  .sidebar .nav-item:hover { background: var(--raised); color: var(--ink); }
  .sidebar .nav-item[aria-current="page"] { background: color-mix(in srgb, var(--accent) 12%, transparent); color: var(--brand-ink);
    box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--accent) 30%, transparent); }

  /* ---------- Feedback ---------- */
  .toast {
    display: flex; align-items: center; gap: 0.75rem; width: 100%; max-width: 26rem; padding: 0.75rem 0.875rem 0.75rem 1rem;
    border-radius: 1rem; background: var(--toast-bg); color: var(--toast-ink); font-weight: 600; font-size: 0.9375rem;
    box-shadow: 0 10px 30px -10px rgb(0 0 0 / 0.45), 0 0 0 1px rgb(255 255 255 / 0.04);
    pointer-events: auto; animation: toast-in 200ms ease-out;
  }
  .toast[data-leaving] { animation: toast-out 160ms ease-in forwards; }
  .toast .toast-icon { display: inline-flex; flex-shrink: 0; width: 1.75rem; height: 1.75rem; align-items: center; justify-content: center;
    border-radius: 999px; background: color-mix(in srgb, var(--accent) 22%, transparent); color: var(--accent); }
  .toast[data-kind="error"] .toast-icon { background: color-mix(in srgb, var(--danger) 22%, transparent); color: var(--danger); }
  .toast[data-kind="pb"] { background: linear-gradient(135deg, color-mix(in srgb, var(--accent) 30%, var(--toast-bg)), var(--toast-bg) 60%); }

  .skeleton {
    border-radius: 0.75rem; background: linear-gradient(90deg, var(--raised) 25%, color-mix(in srgb, var(--raised) 55%, var(--card)) 50%, var(--raised) 75%);
    background-size: 200% 100%; animation: shimmer 1.2s linear infinite;
  }

  .empty { display: flex; flex-direction: column; align-items: center; gap: 0.75rem; padding: 2rem 1rem; text-align: center; color: var(--muted); }
  .empty .empty-icon { display: inline-flex; align-items: center; justify-content: center; width: 3.5rem; height: 3.5rem; border-radius: 1.25rem;
    background: color-mix(in srgb, var(--accent) 14%, transparent); color: var(--brand-ink); }
  .empty .empty-icon .icon { width: 1.75rem; height: 1.75rem; }

  /* A progress bar, e.g. compliance */
  .meter { height: 0.375rem; border-radius: 999px; background: var(--raised); overflow: hidden; }
  .meter > span { display: block; height: 100%; border-radius: inherit; background: var(--accent); transition: width 400ms ease; }

  /* The set tick: pops and draws its check when a set is done */
  /* The round tick: an empty ring, then filled gold with a dark check (it pops and the check draws) */
  .tick { display: inline-flex; align-items: center; justify-content: center; width: 2.75rem; height: 2.75rem; border-radius: 999px;
    background: transparent; color: transparent; box-shadow: inset 0 0 0 1.5px var(--line-strong);
    transition: background-color 180ms ease, color 180ms ease, box-shadow 180ms ease, transform 150ms ease; }
  .tick:active { transform: scale(0.92); }
  .tick .icon { width: 1.25rem; height: 1.25rem; stroke-width: 3; }
  [data-done] .tick { background: var(--brand); color: var(--on-brand); box-shadow: none; }
  [data-done] .tick.just-done { animation: tick-pop 320ms cubic-bezier(.3, 1.6, .5, 1); }
  [data-done] .tick.just-done .icon path { stroke-dasharray: 24; animation: tick-draw 260ms ease-out; }
  [data-set-row] { transition: background-color 200ms ease; border-radius: 0.875rem; }
}

/* ---------- The PHASE wordmark in the header (templates/partials/logo.html) ----------
   Plain CSS outside the layers, so it applies before Tailwind has loaded. */
.wordmark { display: block; flex-shrink: 0; width: auto; max-width: none; height: 22px; aspect-ratio: 542 / 68; }
/* Narrow phones: a little smaller, so it stays centred between the buttons either side of it */
@media (max-width: 419px) { .wordmark { height: 18px; } }
@media (min-width: 1024px) { .wordmark { height: 28px; } }
.wordmark-on-light { display: none; }
:root[data-theme="light"] .wordmark-on-dark { display: none; }
:root[data-theme="light"] .wordmark-on-light { display: block; }

/* ---------- Motion ---------- */
@keyframes shimmer { from { background-position: 200% 0; } to { background-position: -200% 0; } }
@keyframes toast-in { from { opacity: 0; transform: translateY(8px) scale(0.98); } to { opacity: 1; transform: none; } }
@keyframes toast-out { to { opacity: 0; transform: translateY(8px) scale(0.98); } }
@keyframes tick-pop { 0% { transform: scale(0.85); } 60% { transform: scale(1.12); } 100% { transform: scale(1); } }
@keyframes tick-draw { from { stroke-dashoffset: 24; } to { stroke-dashoffset: 0; } }
@keyframes page-in { from { opacity: 0; transform: translateY(6px); } to { opacity: 1; transform: none; } }
@keyframes glow { 0% { box-shadow: 0 0 0 0 color-mix(in srgb, var(--accent) 60%, transparent); } 100% { box-shadow: 0 0 0 18px transparent; } }

/* Each page eases in; expanding sections (details) open smoothly */
main { animation: page-in 180ms ease-out; }
@view-transition { navigation: auto; }
::view-transition-old(root), ::view-transition-new(root) { animation-duration: 160ms; }
details > summary { list-style: none; }
details > summary::-webkit-details-marker { display: none; }
details > summary .chevron { transition: transform 180ms ease; }
details[open] > summary .chevron { transform: rotate(180deg); }
details[open] > :not(summary) { animation: page-in 180ms ease-out; }
.pb-glow { animation: glow 900ms ease-out 2; }
/* HTMX: whatever is being replaced fades a little while the new part loads */
.htmx-request.htmx-fade, .htmx-request .htmx-fade { opacity: 0.55; transition: opacity 150ms ease; }

/* The in-page "are you sure?" box (Phase.confirm in static/js/ui.js) */
.confirm-dialog { margin: auto; width: min(26rem, calc(100vw - 2rem)); border: 1px solid var(--line); border-radius: 1.5rem;
  background: var(--card); color: var(--ink); padding: 1.5rem; box-shadow: 0 30px 80px -20px rgb(0 0 0 / 0.6); }
.confirm-dialog::backdrop { background: rgb(0 0 0 / 0.55); backdrop-filter: blur(3px); }
.confirm-dialog h2 { font-size: 1.25rem; font-weight: 800; margin-bottom: 0.375rem; }
.confirm-dialog p { color: var(--muted); font-size: 0.9375rem; }
.confirm-actions { display: grid; grid-template-columns: 1fr 1fr; gap: 0.5rem; margin-top: 1.25rem; }
.confirm-actions .confirm-extra { grid-column: 1 / -1; }  /* e.g. "Save", across the top */
.confirm-actions .confirm-extra[hidden] { display: none; }
.confirm-dialog[open] { animation: page-in 160ms ease-out; }

/* A section title above a group of exercises ("Key lift"): a clear gap, the title, a hairline */
@layer components {
  .section-title { display: flex; align-items: center; gap: 0.75rem; margin: 1.5rem 0 0.625rem; font-size: 0.6875rem; font-weight: 800;
    letter-spacing: 0.16em; text-transform: uppercase; color: var(--muted); }
  .section-title:first-child { margin-top: 0.25rem; }
}

/* The Train screen's month calendar (templates/training/partials/train_calendar.html) */
@layer components {
  .train-day { position: relative; display: flex; min-height: 3.5rem; flex-direction: column; align-items: center; gap: 0.25rem;
    border-radius: 0.875rem; padding: 0.375rem 0.125rem; font-weight: 700; font-size: 0.9375rem; transition: background-color 150ms; }
  .train-day:hover { background: var(--raised); }
  .train-day.is-other { color: color-mix(in oklab, var(--muted) 55%, transparent); }
  .train-day.is-deload { background: color-mix(in oklab, var(--accent) 12%, transparent); }
  .train-date { display: inline-flex; width: 1.875rem; height: 1.875rem; align-items: center; justify-content: center; border-radius: 9999px;
    font-variant-numeric: tabular-nums; line-height: 1; }
  .train-day.is-today .train-date { background: var(--brand); color: var(--on-brand); }
  .train-day.is-today { box-shadow: inset 0 0 0 2px var(--accent); }
  .train-marks { display: flex; height: 0.625rem; align-items: center; gap: 0.1875rem; }
  .train-mark { display: inline-block; width: 0.5625rem; height: 0.5625rem; border-radius: 9999px; flex-shrink: 0; }
  .train-mark.is-completed { background: var(--accent); }
  .train-mark.is-upcoming { box-shadow: inset 0 0 0 2px var(--accent); }
  .train-mark.is-missed { width: 0; height: 0; border-radius: 0; border-inline: 5px solid transparent; border-bottom: 9px solid var(--danger); }
  /* A short session name, where there's room */
  .train-label { display: none; max-width: 100%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; border-radius: 0.375rem;
    padding: 0.0625rem 0.25rem; font-size: 0.6875rem; font-weight: 700; line-height: 1.3; }
  .train-label.is-completed { background: var(--accent); color: var(--on-accent); }
  .train-label.is-upcoming { box-shadow: inset 0 0 0 1.5px var(--accent); color: var(--brand-ink); }
  .train-label.is-missed { background: color-mix(in oklab, var(--danger) 18%, transparent); color: var(--danger); }
  @media (min-width: 480px) {
    .train-day { min-height: 4.75rem; }
    .train-label { display: block; }
    .train-marks { display: none; }
  }
}

/* Demo videos: the play button ({% video_button %}) and the player (partials/video_sheet.html).
   The button is in the components layer, so utilities (absolute, size-9...) can change it. */
@layer components {
  .video-btn { display: inline-flex; flex-shrink: 0; align-items: center; justify-content: center; border-radius: 9999px;
    background: color-mix(in oklab, var(--accent) 18%, transparent); color: var(--brand-ink); vertical-align: middle;
    transition: background-color 120ms; }
  .video-btn:hover { background: color-mix(in oklab, var(--accent) 30%, transparent); }
  .video-btn:focus-visible { outline: 2px solid var(--brand-ink); outline-offset: 2px; }
  .video-btn[hidden] { display: none; }
  .video-btn .icon { fill: currentColor; margin-left: 2px; }  /* a solid triangle, nudged to look centred */
  .video-btn-md { width: 2.75rem; height: 2.75rem; }
  /* Small in a list, but still easy to tap: the tappable area reaches past the circle */
  .video-btn-sm { position: relative; width: 1.75rem; height: 1.75rem; margin: -0.25rem 0 -0.25rem 0.375rem; }
  .video-btn-sm::after { content: ""; position: absolute; inset: -0.5rem; }
}
/* From the bottom on phones */
.video-sheet { margin: auto 0 0; width: 100%; max-width: 100%; max-height: 92dvh; border: 1px solid var(--line); border-bottom: 0;
  border-radius: 1.5rem 1.5rem 0 0; background: var(--card); color: var(--ink); padding: 0.5rem 0 env(safe-area-inset-bottom);
  box-shadow: 0 30px 80px -20px rgb(0 0 0 / 0.6); overflow: auto; }
.video-sheet::backdrop { background: rgb(0 0 0 / 0.6); backdrop-filter: blur(3px); }
.video-sheet[open] { animation: sheet-up 220ms cubic-bezier(.2,.8,.2,1); }
@keyframes sheet-up { from { transform: translateY(40%); opacity: 0; } }
.video-frame { background: #000; aspect-ratio: 16 / 9; width: 100%; }
.video-frame.is-tall { aspect-ratio: 9 / 16; max-height: 70dvh; width: auto; margin-inline: auto; }
.video-frame iframe, .video-frame video { display: block; width: 100%; height: 100%; border: 0; object-fit: contain; }
.video-frame:has(video) { aspect-ratio: auto; width: 100%; }
.video-frame video { max-height: 70dvh; height: auto; }
/* A box in the middle on bigger screens */
@media (min-width: 640px) {
  .video-sheet { margin: auto; width: min(44rem, calc(100vw - 3rem)); border-bottom: 1px solid var(--line); border-radius: 1.5rem; padding-bottom: 0; }
  .video-sheet[open] { animation: page-in 160ms ease-out; }
  .video-frame.is-tall { max-height: 75dvh; }
}

/* Respect "reduce motion": no movement, just instant changes */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after { animation-duration: 1ms !important; animation-iteration-count: 1 !important; transition-duration: 1ms !important; scroll-behavior: auto !important; }
  @view-transition { navigation: none; }
}

/* The offline / sync status pill (static/js/offline.js): small, at the top of the page */
.sync-pill { margin-bottom: 0.75rem; max-width: 100%;
  display: inline-flex; align-items: center; gap: 0.375rem; padding: 0.375rem 0.875rem; border-radius: 999px;
  font-size: 0.8125rem; font-weight: 700; white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
  background: var(--raised); color: var(--ink); box-shadow: 0 8px 24px -12px rgb(0 0 0 / 0.5); text-decoration: none; }
.sync-pill[hidden] { display: none; }
.sync-pill[data-kind="offline"] { background: color-mix(in srgb, #f59e0b 22%, var(--card)); color: var(--warn-ink); }
.sync-pill[data-kind="synced"] { background: var(--brand); color: var(--on-brand); }
.sync-pill[data-kind="error"], .sync-pill[data-kind="conflict"] { background: color-mix(in srgb, #f59e0b 22%, var(--card)); color: var(--warn-ink); }

/* Two rows with the same label (static/js/rows_editor.js): amber, with "Duplicate label · Use A3" */
.label-duplicate { box-shadow: inset 0 0 0 1px rgb(251 191 36 / 0.6); background: color-mix(in srgb, #f59e0b 12%, transparent) !important; }
.label-duplicate input[name$='label'] { background: color-mix(in srgb, #f59e0b 30%, var(--card)) !important; }

/* A set row's "Saved ✓" (static/js/autosave.js): on top of the row's corner, fading in and out, so it never moves anything */
.row-saved { position: absolute; right: 0.25rem; top: -0.35rem; z-index: 1; padding: 0 0.375rem; border-radius: 999px;
  font-size: 0.6875rem; font-weight: 700; line-height: 1.25rem; color: var(--success); background: var(--card);
  opacity: 0; pointer-events: none; transition: opacity 250ms ease; }
.row-saved[data-show] { opacity: 1; }
@media (prefers-reduced-motion: reduce) { .row-saved { transition: none; } }

/* Unilateral set rows (partials/log_set_row_sides.html): left and right boxes, or, with "Same weight both
   sides" ticked (data-same="on" on the exercise), one kg and one reps box used for both */
.sides-grid { display: grid; grid-template-columns: 0.875rem repeat(4, minmax(0, 1fr)) 3rem 1.5rem; }
.sides-grid.no-tick { grid-template-columns: 0.875rem repeat(4, minmax(0, 1fr)) 1.5rem; }
[data-same="on"] .sides-grid { grid-template-columns: 0.875rem minmax(0, 1.75fr) minmax(0, 1fr) 3rem 1.5rem; }
[data-same="on"] .sides-grid.no-tick { grid-template-columns: 0.875rem minmax(0, 1.75fr) minmax(0, 1fr) 1.5rem; }
.same-only { display: none; }
[data-same="on"] .same-only { display: inline; }
[data-same="on"] [data-side="R"], [data-same="on"] .split-only { display: none !important; }

/* The top bar on phones (base.html): 56px for its buttons, plus the status bar or notch above them
   (the app draws under it). Before, the inset was taken out of the 56px, so on notched iPhones the
   buttons spilled below the bar and over the top of the page. --safe-top is the inset (tests set it). */
:root { --safe-top: env(safe-area-inset-top, 0px); }
.app-header-row { height: calc(3.5rem + var(--safe-top)); padding-top: var(--safe-top); }

/* ---------- The session screen (templates/training/partials/log_exercise.html, docs/phase-style-A.png) ---------- */
/* A set: number, kg box, reps box, round tick, × */
.set-grid { display: grid; grid-template-columns: 0.75rem minmax(0, 1.7fr) minmax(0, 1fr) 2.75rem 1.25rem; gap: 0.375rem; }
.set-grid.no-tick { grid-template-columns: 0.75rem minmax(0, 1.7fr) minmax(0, 1fr) 1.25rem; }
@media (min-width: 640px) { .set-grid { gap: 0.625rem; grid-template-columns: 1rem minmax(0, 1.5fr) minmax(0, 1fr) 2.75rem 1.75rem; } }
/* A big bold number with its unit small after it ("70 kg", "4 reps") */
.pill-box { display: flex; align-items: baseline; justify-content: center; gap: 0.25rem; min-width: 0; height: 3.25rem; padding: 0 0.5rem;
  border-radius: 0.875rem; cursor: text; }
.pill-solo { background: var(--raised); border: 1px solid transparent; align-items: center; }
.pill-solo:focus-within { border-color: var(--accent); box-shadow: 0 0 0 3px color-mix(in srgb, var(--accent) 28%, transparent); }
.pill-solo.is-invalid { border-color: var(--danger); }
/* A fixed width (not sized to what's typed), so filling a box never moves its unit: the page stays still */
.pill-box .pill { width: 4.4ch; min-width: 0; max-width: 100%; height: auto; padding: 0; background: transparent;
  border: 0; box-shadow: none; text-align: right; font-size: 1.25rem; }
.pill-solo .pill { width: 3.4ch; }
.pill-box .pill:focus { box-shadow: none; }
.pill-unit { flex-shrink: 0; font-size: 0.6875rem; font-weight: 700; color: var(--muted); }
.stepper { height: 3.25rem; }
.stepper .pill-box { flex: 1; height: 100%; padding: 0; align-items: center; }
.stepper button { width: 1.375rem; margin: 0 0.125rem; color: color-mix(in srgb, var(--muted) 70%, transparent); }
@media (min-width: 640px) { .stepper button { width: 2.25rem; } }

/* Exercises: the open one shows everything; the rest just their top line and a round mark */
.exercise .exercise-body { display: none; }
.exercise[data-open] .exercise-body { display: block; }
.exercise[data-open] .exercise-mark { display: none; }
.exercise:not([data-open]) .exercise-tools { display: none; }
.exercise-mark { display: inline-flex; align-items: center; justify-content: center; flex-shrink: 0; width: 2.5rem; height: 2.5rem;
  border-radius: 999px; color: transparent; box-shadow: inset 0 0 0 1.5px var(--line-strong); align-self: center; }
.exercise[data-complete] .exercise-mark { background: var(--brand); color: var(--on-brand); box-shadow: none; }
.exercise .exercise-mark .icon { stroke-width: 3; }

/* The label badge (A1): solid gold */
.label-badge { display: inline-flex; flex-shrink: 0; align-items: center; justify-content: center; min-width: 2.25rem; height: 2.25rem;
  padding: 0 0.375rem; border-radius: 0.625rem; background: var(--brand); color: var(--on-brand); font-size: 0.8125rem; font-weight: 800; }

/* The rest timer, above "Complete session" while resting */
.rest-bar { display: flex; align-items: center; gap: 0.75rem; margin-bottom: 0.625rem; padding: 0.75rem 1rem; border-radius: 1rem;
  background: var(--card); border: 1px solid var(--line); }
.rest-bar[hidden] { display: none; }
.rest-bar button { min-height: 2.75rem; padding: 0 0.375rem; font-size: 0.875rem; font-weight: 700; color: var(--muted); }
.rest-bar button:hover { color: var(--ink); }
.rest-bar.is-done { border-color: var(--accent); }

/* Appearance → Colours (templates/accounts/account.html): the pickers only for Custom */
[data-colours-form]:not(:has(input[name="theme_choice"][value="custom"]:checked)) [data-custom-colours] { display: none; }

/* The "previous weeks" strip on the session screen (log_exercise.html): one tile a week, on one row;
   longer blocks (7+ weeks) scroll sideways inside the strip */
.week-strip { display: grid; grid-auto-flow: column; grid-auto-columns: minmax(3.25rem, 1fr); gap: 0.375rem; overflow-x: auto;
  scrollbar-width: none; overscroll-behavior-x: contain; }
.week-strip::-webkit-scrollbar { display: none; }
.week-tile { position: relative; display: flex; width: 100%; min-height: 3.25rem; flex-direction: column; align-items: center; justify-content: center;
  border-radius: 0.75rem; background: var(--raised); border: 1.5px solid transparent; color: var(--ink); }
.week-tile:disabled { cursor: default; color: var(--muted); opacity: 1; }
.week-tile.is-current { border-color: var(--accent); }
.week-pb { position: absolute; top: 0.3rem; right: 0.3rem; width: 0.375rem; height: 0.375rem; border-radius: 999px; background: var(--accent); }
.week-popover { margin: auto; padding: 0.875rem 1rem; max-width: min(20rem, calc(100vw - 2rem)); border-radius: 1rem; border: 1px solid var(--line);
  background: var(--card); color: var(--ink); box-shadow: 0 20px 50px -20px rgb(0 0 0 / 0.6); }
.week-popover::backdrop { background: rgb(0 0 0 / 0.35); }

/* ---------- The annual planner's grid (templates/training/planner.html) ----------
   Each week a fixed width (68px on laptops, 52px on phones: three or four months in view), scrolled
   sideways inside the card, the row labels pinned on the left. "Season" squeezes the whole year in:
   colours and dots, no names. */
.planner-scroll { scrollbar-width: thin; overscroll-behavior-x: contain; scroll-behavior: smooth; }
.planner-grid { --col: 3.25rem; position: relative; display: grid; grid-template-columns: 5.75rem repeat(var(--weeks), var(--col));
  grid-template-rows: 1.75rem 2.75rem 3rem 3rem 2.5rem 1rem; row-gap: 0.375rem; padding: 0.75rem 0.75rem 0.5rem 0; width: max-content; }
@media (min-width: 1024px) { .planner-grid { --col: 4.25rem; } }
.planner-label { position: sticky; left: 0; z-index: 4; grid-column: 1; display: flex; align-items: center; padding-left: 1rem;
  background: var(--card); box-shadow: 8px 0 8px -8px rgb(0 0 0 / 0.25); }
.planner-month { align-self: end; padding: 0 0.375rem 0.25rem; border-left: 1px solid var(--line); font-size: 0.75rem; font-weight: 800; white-space: nowrap; }
/* A month's name and a phase's name stay in view while its weeks are scrolled past */
.planner-month > b, .planner-phase > span:first-child { position: sticky; left: 6.25rem; }
.planner-week { justify-self: center; align-self: center; width: 2.25rem; height: 2.25rem; min-height: 0; border-radius: 999px;
  font-size: 0.8125rem; font-weight: 700; color: var(--muted); font-variant-numeric: tabular-nums; touch-action: none; user-select: none; }
.planner-week:hover { background: var(--raised); color: var(--ink); }
.planner-week.is-current { position: relative; z-index: 3; background: var(--brand); color: var(--on-brand); }
.planner-week.is-picked { background: color-mix(in srgb, var(--accent) 25%, transparent); color: var(--ink); }
/* Tap a week's Games or Events space to add one there: nothing shows until it's hovered */
.planner-cell { min-height: 0; margin: 0.125rem; border-radius: 0.5rem; background: transparent; color: transparent; font-size: 1rem; }
.planner-cell:hover, .planner-cell:focus-visible { background: var(--raised); color: var(--muted); }
/* A phase: one bar across its weeks with its name and length, a subtle gradient of its colour; rounded in dark mode, a pill in light */
.planner-phase { position: relative; z-index: 1; display: flex; align-items: center; justify-content: space-between; gap: 0.5rem; margin: 0 0.1875rem;
  padding: 0 0.75rem; border-radius: 0.625rem; color: var(--phase-ink); font-size: 0.8125rem; font-weight: 800; white-space: nowrap;
  background: linear-gradient(90deg, var(--phase), color-mix(in srgb, var(--phase) 78%, #000)); }
.planner-phase > span { overflow: hidden; text-overflow: ellipsis; }
:root[data-theme="light"] .planner-phase { border-radius: 999px; background: linear-gradient(90deg, var(--phase), color-mix(in srgb, var(--phase) 82%, #fff)); }
/* A tooltip (one-week phases, game tiles): on hover, or focus after a tap */
[data-tip]:hover::after, [data-tip]:focus-visible::after {
  content: attr(data-tip); position: absolute; bottom: calc(100% + 0.375rem); left: 50%; transform: translateX(-50%); z-index: 6;
  padding: 0.25rem 0.5rem; border-radius: 0.5rem; background: var(--ink); color: var(--surface); font-size: 0.6875rem; font-weight: 700;
  white-space: nowrap; pointer-events: none; }
/* A game: "H" or "A" on top, the opponent under it; home a solid gold tile, away a gold outline */
.planner-game { position: relative; z-index: 1; display: flex; flex-direction: column; align-items: center; justify-content: center; margin: 0.125rem 0.25rem;
  min-width: 0; border-radius: 0.625rem; background: var(--brand); color: var(--on-brand); font-size: 0.6875rem; font-weight: 700;
  line-height: 1.15; padding: 0 0.25rem; border: 1.5px solid var(--accent); }
.planner-game > span { max-width: 100%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.planner-game.is-away { background: transparent; color: var(--brand-ink); }
.planner-event { z-index: 1; display: flex; align-items: center; margin: 0.25rem 0.1875rem; padding: 0 0.625rem; min-width: 0; border-radius: 999px;
  background: var(--raised); border: 1px solid var(--line); font-size: 0.75rem; font-weight: 700; white-space: nowrap; overflow: hidden; }
/* TODAY: a thin gold line from under the week numbers down through the rows (behind bars and tiles, so never over their text), labelled at the bottom */
.planner-today { position: relative; z-index: 0; justify-self: center; width: 2px; background: var(--accent); pointer-events: none; }
.planner-today span { position: absolute; bottom: -1rem; left: 50%; transform: translateX(-50%); padding: 0 0.3rem; border-radius: 0.25rem;
  background: var(--accent); color: var(--on-accent); font-size: 0.5625rem; font-weight: 800; letter-spacing: 0.12em; text-transform: uppercase; }

/* Season: the whole year in the card's width */
.planner-scroll[data-zoom="season"] .planner-grid { width: 100%; grid-template-columns: 5.75rem repeat(var(--weeks), minmax(0.5rem, 1fr)); }
.planner-scroll[data-zoom="season"] .planner-week { width: 0.5rem; height: 0.5rem; font-size: 0; background: var(--line); }
.planner-scroll[data-zoom="season"] .planner-week.is-current { background: var(--brand); }
.planner-scroll[data-zoom="season"] .planner-phase { padding: 0; margin: 0 1px; border-radius: 0.375rem; font-size: 0; }
.planner-scroll[data-zoom="season"] .planner-game { margin: auto; width: 0.625rem; height: 0.625rem; min-height: 0; padding: 0; border-radius: 999px; font-size: 0; }
.planner-scroll[data-zoom="season"] .planner-event { margin: 0.75rem 1px; padding: 0; font-size: 0; }
.planner-scroll[data-zoom="season"] .planner-month { font-size: 0.6875rem; padding-left: 0.25rem; }
.planner-scroll[data-zoom="season"] .planner-cell { display: none; }
