  :root {
    --canvas:#F4F5F7; --surface:#FFFFFF; --ink:#191C22; --ink-2:#434955; --muted:#3F434B;
    --faint:#565C66; --line:#E6E8ED; --line-2:#F0F1F4; --inset:#F6F7F9;
    --accent:#FF1744; --accent-weak:#FFE3E9;
    --pop:#FF1744; --pop-ink:#FFFFFF;
    --swim:#2E90FA; --bike:#7C5CFF; --run:#FF4D8D; --other:#F59E0B;
    --fresh:#57B0FF; --optimal:#22C1DC; --tired:#D97706; --hard:#FF3B5C;
    /* Session-feel ramp, best->worst: green, yellow, amber, orange, red. Chosen to
       stay legible as text on the white surface (the "Feel" chip + selected button). */
    --feel-great:#1E9E57; --feel-good:#CA8A04; --feel-ok:#E37F1B; --feel-rough:#D9502A; --feel-bad:#E23B57;
    --shadow:0 1px 2px rgba(25,28,34,.05);
    --shadow-pop:0 4px 14px rgba(25,28,34,.10), 0 1px 3px rgba(25,28,34,.07);
    /* Spatial system. Radius: one tight scale (chips -> controls -> cards -> modals)
       instead of ~15 ad-hoc values. Spacing: a 4pt grid. Use these, not raw px. */
    --r-sm:8px; --r-md:10px; --r-lg:12px; --r-xl:16px; --r-pill:999px;
    --s-1:4px; --s-2:8px; --s-3:12px; --s-4:16px; --s-5:20px; --s-6:24px; --s-8:32px;
    --mono:"Switzer",-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,sans-serif;
    --sans:"Switzer",-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,sans-serif;
    --display:"Switzer",-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,sans-serif;
    --logo:"obviously","Switzer",-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,sans-serif;   /* OSO wordmark = Obviously (Adobe Fonts kit kjm6mtf), italic; Switzer italic falls back while the kit loads */
    /* Type signature: wide, deliberate tracking on uppercase labels (editorial, not generic-SaaS). Tune globally here. */
    --track-caps:.1em; --track-btn:.07em; --track-head:.05em;
    /* Semantic type scale — the app UI uses ONLY these 5 roles. */
    --fs-caption:13px;   /* eyebrows, data labels, meta, table headers */
    --fs-body:15px;      /* default body, values, buttons */
    --fs-subhead:18px;   /* column labels, sub-section titles, emphasis */
    --fs-heading:22px;   /* card / section titles */
    --fs-title:30px;     /* page titles, big stat display */
    color-scheme:light;
  }
  * { box-sizing:border-box; }
  body { margin:0; background:var(--canvas); color:var(--ink); font-family:var(--sans);
    -webkit-font-smoothing:antialiased; text-rendering:optimizeLegibility; font-size:15px; line-height:1.45; }
  a { color:inherit; text-decoration:none; }
  .sep { display:inline-block; width:3px; height:3px; border-radius:50%; background:var(--faint); vertical-align:middle; margin:0 8px; }
  .tri { width:0; height:0; border-left:4px solid transparent; border-right:4px solid transparent; display:inline-block; }
  .tri.up { border-bottom:5px solid currentColor; } .tri.down { border-top:5px solid currentColor; }

  .app { display:grid; grid-template-columns:212px 1fr; min-height:100vh; }

  /* RAIL */
  .rail { background:var(--surface); border-right:1px solid var(--line); display:flex; flex-direction:column;
    align-items:stretch; gap:2px; padding:16px 12px; position:sticky; top:0; height:100vh; }
  .logo { width:34px; height:34px; border-radius:var(--r-md); margin-bottom:18px; background:var(--ink);
    display:grid; place-items:center; color:var(--surface); flex:none; }
  .logo svg { width:19px; height:19px; }
  .nav-btn { width:42px; height:40px; border-radius:var(--r-md); border:0; background:transparent; color:var(--faint);
    display:grid; place-items:center; cursor:pointer; transition:background .14s,color .14s; position:relative; }
  .nav-btn svg { width:20px; height:20px; }
  .nav-btn:hover { background:var(--inset); color:var(--ink-2); }
  .nav-btn.active { background:var(--inset); color:var(--ink); }
  .nav-btn.active::before { content:""; position:absolute; left:-12px; top:9px; bottom:9px; width:3px; border-radius:0 3px 3px 0; background:var(--ink); }
  .rail-spacer { flex:1; }
  .avatar { width:34px; height:34px; border-radius:50%; margin-top:10px; background:var(--ink); color:var(--surface);
    display:grid; place-items:center; font-weight:600; font-size:15px; }

  /* MAIN + HEADER */
  .main { min-width:0; }
  .screen { padding:26px 34px 64px; max-width:1360px; }
  .topbar { display:flex; align-items:flex-start; gap:20px; margin-bottom:24px; }
  .htitle h1 { margin:0; font-family:var(--display); font-size:30px; font-weight:600; letter-spacing:-.025em; }
  .htitle p { margin:5px 0 0; color:var(--muted); font-size:15px; }
  .topbar-right { margin-left:auto; display:flex; align-items:center; gap:10px; flex-wrap:wrap; justify-content:flex-end; }
  /* Segmented control: switches WHICH VIEW of the same data you're looking at.
     One implementation for every tab strip in the app - Compare's modes, the
     Records tabs, the chart's Time/Distance switch. Filters are a different
     affordance and use .fchip below. */
  .seg { display:inline-flex; background:var(--inset); border:1px solid var(--line);
    border-radius:var(--r-md); padding:3px; gap:2px; }
  .seg button { border:0; background:transparent; color:var(--muted); cursor:pointer;
    font-family:var(--sans); font-size:13px; font-weight:700; letter-spacing:var(--track-btn);
    padding:7px 14px; border-radius:var(--r-sm); white-space:nowrap;
    transition:background .14s ease, color .14s ease; }
  .seg button:hover { color:var(--ink); }
  .seg button.on { background:var(--ink); color:var(--surface); }
  .seg button.on:hover { color:var(--surface); }
  /* Sliding tab strip (Records + Compare top toggles): the black selection is a
     single thumb that SLIDES between tabs (dom.slideSeg sets its transform/width)
     instead of the .on background hard-jumping. Buttons go transparent so the
     thumb shows through. */
  .seg-slide { position:relative; }
  .seg-slide .seg-thumb { position:absolute; left:0; top:3px; height:calc(100% - 6px); width:0;
    background:var(--ink); border-radius:var(--r-sm); z-index:0; pointer-events:none;
    transition:transform .3s cubic-bezier(.4,0,.2,1), width .3s cubic-bezier(.4,0,.2,1); }
  .seg-slide button { position:relative; z-index:1; }
  .seg-slide button.on, .seg-slide button.on:hover { background:transparent; color:var(--surface); }
  @media (prefers-reduced-motion:reduce){ .seg-slide .seg-thumb { transition:none; } }
  .btn { border:1px solid var(--line); background:var(--surface); color:var(--ink); cursor:pointer; font-family:var(--sans);
    font-weight:600; font-size:15px; padding:9px 14px; border-radius:var(--r-md); display:inline-flex; align-items:center; gap:7px; transition:border-color .14s; }
  .btn:hover { border-color:var(--muted); }
  .btn svg { width:15px; height:15px; }
  .btn-primary { border:0; background:var(--ink); color:var(--surface); }
  .btn-primary:hover { opacity:.92; }
  .btn-ghost { border-color:transparent; background:transparent; color:var(--accent); }

  /* GRID + CARDS */
  .grid { display:grid; grid-template-columns:repeat(12,1fr); gap:16px; }
  .card { background:var(--surface); border:1px solid var(--line); border-radius:var(--r-lg); padding:18px 18px 17px; box-shadow:var(--shadow); position:relative; }
  /* Surface hierarchy: primary content sits on the elevated white card above;
     SECONDARY and NESTED content recedes onto a flat inset panel (no shadow), so a
     screen reads as two levels instead of a wall of identical cards. `.flat` is the
     reusable recessed variant; nested cards and the dashboard intro use it. */
  .card.flat, .card .card { background:var(--inset); box-shadow:none; }
  .card .card{ border-color:var(--line-2); }
  .card.pad0 { padding:0; overflow:hidden; }
  .card-head { display:flex; align-items:center; gap:8px; margin-bottom:15px; }
  .eyebrow { font-family:var(--sans); font-size:15px; letter-spacing:var(--track-head); text-transform:uppercase; color:var(--ink); font-weight:700; margin:0; }
  /* unified section heading (sans, sentence-case) — deliberately NOT the mono eyebrow look */
  .sect-h { font-family:var(--sans); font-size:15px; font-weight:700; letter-spacing:var(--track-head); text-transform:uppercase; color:var(--ink); margin:0; }
  .card-head .spacer { flex:1; }
  .chip { font-family:var(--mono); font-size:13px; letter-spacing:var(--track-caps); font-weight:600; text-transform:uppercase; white-space:nowrap; }
  .link { font-family:var(--mono); font-size:13px; letter-spacing:var(--track-caps); text-transform:uppercase; color:var(--accent); cursor:pointer; font-weight:600; }
  .col-3{grid-column:span 3}.col-4{grid-column:span 4}.col-5{grid-column:span 5}.col-6{grid-column:span 6}
  .col-7{grid-column:span 7}.col-8{grid-column:span 8}.col-9{grid-column:span 9}.col-12{grid-column:span 12}

  /* readiness ring */
  .ring-wrap { display:flex; align-items:center; gap:20px; }
  .ring { position:relative; width:124px; height:124px; flex:none; }
  .ring-center { position:absolute; inset:0; display:flex; flex-direction:column; align-items:center; justify-content:center; }
  .ring-center .val { font-family:var(--display); font-size:30px; font-weight:600; letter-spacing:-.03em; line-height:1; }
  .ring-center .lab { font-family:var(--mono); font-size:13px; letter-spacing:var(--track-caps); color:var(--muted); text-transform:uppercase; font-weight:600; margin-top:5px; }
  .vitals { display:flex; flex-direction:column; gap:11px; flex:1; }
  .vital { display:flex; align-items:baseline; justify-content:space-between; gap:8px; border-bottom:1px solid var(--line-2); padding-bottom:9px; }
  .vital:last-child { border-bottom:0; padding-bottom:0; }
  .vital .k { font-size:15px; color:var(--muted); } .vital .v { font-family:var(--mono); font-weight:600; font-size:22px; font-variant-numeric:tabular-nums; }
  .vital .v small { color:var(--faint); font-size:15px; font-weight:500; }

  .tiles { display:grid; grid-template-columns:1fr 1fr; gap:11px; }
  .tile { border:1px solid var(--line); border-radius:var(--r-md); padding:12px 13px; }
  .tile .k { font-family:var(--mono); font-size:13px; letter-spacing:var(--track-caps); text-transform:uppercase; font-weight:600; color:var(--faint); }
  .tile .v { font-family:var(--display); font-size:30px; font-weight:600; letter-spacing:-.03em; margin-top:5px; font-variant-numeric:tabular-nums; }
  .tile .d { font-size:15px; margin-top:3px; display:flex; align-items:center; gap:5px; color:var(--muted); }
  .up{color:var(--optimal)} .down{color:var(--hard)}
  .tile .spark { margin-top:9px; height:24px; width:100%; display:block; }

  .session-title { font-family:var(--display); font-size:22px; font-weight:600; letter-spacing:-.02em; margin:0 0 3px; }
  .session-sub { color:var(--muted); font-size:15px; margin-bottom:15px; }
  .interval-bar { display:flex; gap:3px; height:38px; align-items:flex-end; margin-bottom:15px; }
  .interval-bar span { border-radius:2px; flex:1; }
  .session-metrics { display:flex; gap:24px; margin-bottom:15px; flex-wrap:wrap; }
  .sm .k { font-family:var(--mono); font-size:13px; letter-spacing:var(--track-caps); text-transform:uppercase; font-weight:600; color:var(--faint); }
  .sm .v { font-family:var(--display); font-size:22px; font-weight:600; font-variant-numeric:tabular-nums; letter-spacing:-.01em; margin-top:2px; }
  .coach-inline { background:var(--inset); border:1px solid var(--line); border-radius:var(--r-md); padding:11px 12px; display:flex; gap:10px; font-size:15px; color:var(--ink-2); line-height:1.45; }
  .coach-inline .mk { width:18px; height:18px; border-radius:var(--r-sm); background:var(--accent); flex:none; display:grid; place-items:center; margin-top:1px; }
  .coach-inline .mk svg { width:11px; height:11px; color:#fff; }

  .legend { display:flex; gap:15px; align-items:center; flex-wrap:wrap; }
  .lg { display:inline-flex; align-items:center; gap:6px; font-size:15px; color:var(--muted); }
  .lg i { width:10px; height:10px; border-radius:3px; display:inline-block; }

  .ff-wrap { position:relative; }
  .ff-tip { position:absolute; pointer-events:none; background:var(--surface); color:var(--ink); border:1px solid var(--line);
    border-radius:var(--r-md); padding:9px 11px; font-size:15px; box-shadow:var(--shadow-pop); opacity:0; transition:opacity .12s; min-width:150px; z-index:5; }
  .ff-tip .td { font-family:var(--mono); font-size:13px; letter-spacing:var(--track-caps); color:var(--muted); margin-bottom:7px; text-transform:uppercase; font-weight:600; }
  .ff-tip .tr { display:flex; align-items:center; justify-content:space-between; gap:14px; margin:4px 0; }
  .ff-tip .tr span:first-child { display:inline-flex; align-items:center; gap:6px; color:var(--muted); }
  .ff-tip .tr b { font-family:var(--mono); font-variant-numeric:tabular-nums; font-weight:600; }
  /* hairline between the day's numbers and its sessions in the chart tooltip */
  .ff-tip .ff-sep { height:1px; background:var(--line); margin:8px 0 6px; }
  .ff-tip i { width:9px; height:9px; border-radius:2px; display:inline-block; }

  .wl { display:flex; align-items:flex-end; gap:9px; height:146px; padding-top:6px; }
  .wl-col { flex:1; display:flex; flex-direction:column; align-items:center; gap:8px; height:100%; justify-content:flex-end; }
  .wl-stack { width:100%; max-width:26px; display:flex; flex-direction:column-reverse; gap:2px; }
  .wl-stack span { display:block; } .wl-stack span:first-child{border-radius:0 0 3px 3px} .wl-stack span:last-child{border-radius:3px 3px 0 0}
  .wl-x { font-family:var(--mono); font-size:15px; color:var(--faint); } .wl-x.now{color:var(--ink);font-weight:700}

  .zone-row { display:flex; align-items:center; gap:10px; margin:10px 0; }
  .zone-row .zk { font-family:var(--mono); font-size:15px; color:var(--muted); width:96px; flex:none; }
  .zone-track { flex:1; height:8px; background:var(--inset); border-radius:var(--r-sm); overflow:hidden; }
  .zone-track i { display:block; height:100%; border-radius:var(--r-sm); }
  .zone-row .zv { font-family:var(--mono); font-size:15px; color:var(--ink-2); width:46px; text-align:right; font-variant-numeric:tabular-nums; }

  /* activity feed rows */
  .act { display:flex; align-items:center; gap:13px; padding:12px 2px; border-bottom:1px solid var(--line-2); cursor:pointer; border-radius:var(--r-sm); transition:background .12s; }
  .act:hover { background:var(--inset); }
  .act:last-child { border-bottom:0; }
  .act-ic { width:36px; height:36px; border-radius:var(--r-md); display:grid; place-items:center; flex:none; }
  .act-ic svg { width:19px; height:19px; color:#fff; }
  .act-body { flex:1; min-width:0; }
  .act-title { font-weight:600; font-size:15px; letter-spacing:-.005em; }
  .act-meta { font-size:15px; color:var(--muted); font-family:var(--mono); margin-top:1px; }
  /* Fixed-width columns so every row's stats line up into clean vertical
     columns instead of floating ragged against the right edge. */
  .act-stats { display:grid; grid-template-columns:56px 82px 82px; gap:14px; align-items:baseline; flex:none; }
  .act-stat { text-align:right; }
  .act-stat .k { font-family:var(--mono); font-size:13px; letter-spacing:var(--track-caps); text-transform:uppercase; font-weight:600; color:var(--faint); }
  .act-stat .v { font-family:var(--display); font-weight:600; font-size:15px; font-variant-numeric:tabular-nums; margin-top:2px; }
  @media (max-width:900px){ .act-stats { grid-template-columns:60px 82px; } .act-stats .act-stat:nth-child(2){display:none} }

  .coach-msg { font-size:15px; line-height:1.6; color:var(--ink-2); }
  .coach-msg b { color:var(--ink); font-weight:600; }

  .race { display:flex; align-items:center; gap:18px; }
  .race-days { text-align:center; flex:none; padding-right:18px; border-right:1px solid var(--line); }
  .race-days .n { font-family:var(--display); font-size:30px; font-weight:600; letter-spacing:-.04em; line-height:1; font-variant-numeric:tabular-nums; }
  .race-days .u { font-family:var(--mono); font-size:13px; letter-spacing:var(--track-caps); text-transform:uppercase; font-weight:600; color:var(--muted); margin-top:4px; }
  .race-info h4 { margin:0 0 4px; font-family:var(--display); font-size:22px; font-weight:600; letter-spacing:-.01em; }
  .race-info p { margin:0; font-size:15px; color:var(--muted); }
  .race-tags { display:flex; gap:14px; margin-top:10px; flex-wrap:wrap; }
  .race-tags span { font-family:var(--mono); font-size:13px; letter-spacing:var(--track-caps); text-transform:uppercase; font-weight:600; color:var(--muted); }

  /* CALENDAR */
  .cal { display:grid; grid-template-columns:repeat(7,minmax(0,1fr)) 176px; border:1px solid var(--line); border-radius:var(--r-lg); overflow:hidden; background:var(--surface); }
  .cal-h { font-family:var(--mono); font-size:13px; letter-spacing:var(--track-caps); text-transform:uppercase; font-weight:600; color:var(--muted); padding:10px 12px; border-bottom:1px solid var(--line); background:var(--inset); }
  .cal-h.sum { text-align:left; border-left:1px solid var(--line); }
  .cal-cell { min-width:0; min-height:118px; border-right:1px solid var(--line-2); border-bottom:1px solid var(--line-2); padding:8px 9px; display:flex; flex-direction:column; gap:5px; }
  .cal-cell.week-sum { border-right:0; border-left:1px solid var(--line); align-items:stretch; justify-content:flex-start; gap:0; padding:11px 13px; background:var(--surface); }
  .ws { display:flex; flex-direction:column; gap:8px; width:100%; }
  .ws-load { display:flex; align-items:baseline; gap:5px; flex-wrap:wrap; }
  .ws-load > b { font-size:22px; font-weight:800; font-variant-numeric:tabular-nums; line-height:1; }
  .ws-load small { font-size:15px; color:var(--muted); }
  .ws-plan { width:100%; font-size:15px; color:var(--faint); font-variant-numeric:tabular-nums; }
  .ws-line { display:flex; justify-content:space-between; align-items:baseline; font-size:15px; color:var(--muted); }
  .ws-line b { color:var(--ink); font-weight:700; font-size:15px; font-variant-numeric:tabular-nums; }
  .ws-bar { display:flex; height:6px; border-radius:4px; overflow:hidden; background:var(--inset); margin-top:2px; }
  .ws-bar i { display:block; height:100%; }
  .ws-legend { display:flex; flex-direction:column; gap:4px; margin-top:1px; }
  .ws-sp { display:flex; align-items:center; gap:6px; font-size:15px; color:var(--muted); }
  .ws-sp .ws-spn { flex:1; }
  .ws-sp b { color:var(--ink); font-weight:600; font-variant-numeric:tabular-nums; }
  .ws-dot { width:8px; height:8px; border-radius:50%; flex:none; }
  .cal-cell.dim { background:var(--inset); }
  .cal-cell.today { box-shadow:inset 0 0 0 2px var(--ink); }
  .cal-date { font-family:var(--mono); font-size:15px; color:var(--muted); font-variant-numeric:tabular-nums; display:flex; justify-content:space-between; }
  .cal-date b { color:var(--ink); }
  .cal-w { display:contents; }
  .wo { border-radius:var(--r-sm); padding:5px 7px; font-size:15px; line-height:1.25; border-left:3px solid; background:var(--inset); min-width:0; overflow-wrap:anywhere; }
  .wo.done { background:var(--surface); border:1px solid var(--line); border-left-width:3px; }
  .wo.planned { opacity:.9; border-style:dashed; border:1px dashed var(--line); border-left:3px solid; }
  .wo .wt { font-weight:600; display:block; color:var(--ink); }
  .wo .wm { font-family:var(--mono); font-size:15px; color:var(--muted); }
  .wk-stat { display:flex; flex-direction:column; gap:3px; }
  .wk-stat.plan { margin-top:12px; padding-top:12px; border-top:1px solid var(--line-2); }
  .wk-lab { font-size:13px; letter-spacing:var(--track-caps); text-transform:uppercase; color:var(--faint); font-weight:600; }
  .wk-num { font-family:var(--display); font-size:22px; font-weight:600; line-height:1; font-variant-numeric:tabular-nums; color:var(--ink); }
  .wk-stat.plan .wk-num { color:var(--faint); }

  /* generic table */
  .tbl { width:100%; border-collapse:collapse; }
  .tbl th { text-align:left; font-family:var(--mono); font-size:13px; letter-spacing:var(--track-caps); text-transform:uppercase; color:var(--faint); font-weight:600; padding:8px 10px; border-bottom:1px solid var(--line); }
  .tbl td { padding:11px 10px; border-bottom:1px solid var(--line-2); font-size:15px; font-variant-numeric:tabular-nums; }
  .tbl tr:last-child td { border-bottom:0; }
  .tbl .num { text-align:right; font-family:var(--mono); }
  /* wide data tables scroll horizontally on their own rather than squeezing every column */
  .tblscroll { overflow-x:auto; -webkit-overflow-scrolling:touch; }
  .tbl-wide { min-width:520px; }
  .tbl-wide td, .tbl-wide th { white-space:nowrap; }
  .tbl-wide td:first-child, .tbl-wide th:first-child { white-space:normal; }

  /* filter chips */
  /* Filter chip: narrows WHAT IS IN the list. Pills, so they read as removable
     conditions rather than as a view switch, and they wrap freely. */
  .filters { display:flex; gap:8px; flex-wrap:wrap; align-items:center; }
  .fchip { display:inline-flex; align-items:center; gap:7px; border:1px solid var(--line);
    background:var(--surface); color:var(--muted); border-radius:var(--r-pill); padding:8px 15px;
    font-family:var(--sans); font-size:13px; font-weight:700; text-transform:uppercase;
    letter-spacing:var(--track-btn); cursor:pointer; white-space:nowrap;
    transition:border-color .14s ease, color .14s ease, background .14s ease; }
  .fchip:hover { color:var(--ink); border-color:var(--line-strong,#D3D7DE); }
  .fchip i { width:7px; height:7px; border-radius:50%; }
  .fchip.on { border-color:var(--ink); color:var(--surface); background:var(--ink); }

  /* activity detail */
  .ad-hero { display:flex; gap:26px; align-items:flex-start; flex-wrap:wrap; }
  .ad-metrics { display:grid; grid-template-columns:repeat(4,1fr); gap:1px; background:var(--line-2); border:1px solid var(--line); border-radius:var(--r-md); overflow:hidden; }
  .ad-metric { background:var(--surface); padding:13px 15px; }
  .ad-metric .k { font-family:var(--mono); font-size:13px; letter-spacing:var(--track-caps); text-transform:uppercase; font-weight:600; color:var(--faint); }
  .ad-metric .v { font-family:var(--display); font-size:22px; font-weight:600; letter-spacing:-.02em; margin-top:3px; font-variant-numeric:tabular-nums; }
  .ad-metric .v small { font-size:15px; color:var(--muted); font-weight:500; }
  .chart-y { font-family:var(--mono); font-size:15px; fill:var(--faint); }
  .chart-lab { font-family:var(--mono); font-size:13px; letter-spacing:var(--track-caps); text-transform:uppercase; font-weight:600; color:var(--muted); margin-bottom:6px; display:flex; align-items:center; gap:6px; }
  .chart-lab b { color:var(--ink); font-family:var(--display); font-size:15px; }

  /* map */
  .map { width:100%; height:100%; display:block; background:linear-gradient(180deg,#EEF1F5,#E7EBF0); }
  .map-wrap { border-radius:var(--r-md); overflow:hidden; border:1px solid var(--line); position:relative; }
  #adMap .scrub-cur, #adMap .scrub-halo { transition:cx .1s linear, cy .1s linear; }
  .map-badge { position:absolute; top:12px; left:12px; background:var(--surface); border:1px solid var(--line); border-radius:var(--r-sm); padding:7px 11px; font-family:var(--mono); font-size:15px; box-shadow:var(--shadow); }

  /* routes */
  .route-card { cursor:pointer; transition:border-color .14s, transform .06s; }
  .route-card:hover { border-color:var(--muted); }
  .route-card:active { transform:translateY(1px); }
  .surfbar { display:flex; height:7px; border-radius:var(--r-sm); overflow:hidden; margin:11px 0 4px; }
  .surfbar span { display:block; }
  .surf-legend { display:flex; gap:12px; font-family:var(--mono); font-size:15px; color:var(--muted); }
  .surf-legend i { width:8px; height:8px; border-radius:2px; display:inline-block; margin-right:4px; }
  .pred { display:grid; grid-template-columns:repeat(2,1fr); gap:9px; }
  .pred-box { border:1px solid var(--line); border-radius:var(--r-md); padding:11px 12px; }
  .pred-box .k { font-family:var(--mono); font-size:13px; letter-spacing:var(--track-caps); text-transform:uppercase; font-weight:600; color:var(--faint); }
  .pred-box .v { font-family:var(--display); font-size:22px; font-weight:600; margin-top:3px; font-variant-numeric:tabular-nums; }

  /* explore */
  .stat-row { display:grid; grid-template-columns:repeat(4,1fr); gap:16px; }
  /* reusable text primitives — use these (not inline font-size) in every new section */
  .note { font-size:var(--fs-body); color:var(--muted); line-height:1.5; }
  .stat-flow { display:flex; gap:34px; flex-wrap:wrap; }
  .stat .lab { font-size:13px; text-transform:uppercase; letter-spacing:var(--track-caps); color:var(--muted); font-weight:600; }
  .stat .val { font-size:var(--fs-title); font-weight:800; font-variant-numeric:tabular-nums; margin-top:2px; line-height:1.05; }
  .stat .val.sm { font-size:var(--fs-heading); }
  .stat .sub { font-size:var(--fs-caption); color:var(--faint); margin-top:2px; }
  .bigstat .v { font-family:var(--display); font-size:30px; font-weight:600; letter-spacing:-.03em; font-variant-numeric:tabular-nums; }
  .bigstat .k { font-family:var(--mono); font-size:13px; letter-spacing:var(--track-caps); text-transform:uppercase; font-weight:600; color:var(--muted); margin-top:2px; }
  .pr-row { display:flex; align-items:center; justify-content:space-between; padding:10px 0; border-bottom:1px solid var(--line-2); }
  .pr-row:last-child { border-bottom:0; }
  .pr-k { font-size:15px; color:var(--ink-2); } .pr-v { font-family:var(--mono); font-weight:600; font-variant-numeric:tabular-nums; }
  .pr-tag { font-family:var(--mono); font-size:15px; color:var(--optimal); border:1px solid var(--optimal); border-radius:4px; padding:1px 5px; margin-left:8px; }


  /* settings */
  .set-grid { display:grid; grid-template-columns:1fr 1fr; gap:14px; }
  .field { display:flex; align-items:center; justify-content:space-between; padding:12px 0; border-bottom:1px solid var(--line-2); gap:12px; }
  .field:last-child { border-bottom:0; }
  .field > .btn { white-space:nowrap; flex:0 0 auto; }
  .field label { font-size:15px; color:var(--ink-2); }
  .field .hint { font-size:15px; color:var(--faint); margin-top:2px; }
  .inp{ border:1px solid var(--line); border-radius:var(--r-md); padding:9px 12px; font-family:var(--sans); font-size:15px; background:var(--surface); color:var(--ink); transition:border-color .12s, box-shadow .12s; }
  .inp:hover{ border-color:var(--muted); }
  .inp:focus{ outline:none; border-color:var(--accent); box-shadow:0 0 0 3px var(--accent-weak); }
  select.inp{ -webkit-appearance:none; -moz-appearance:none; appearance:none; cursor:pointer; padding-right:36px; background-image:url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 24 24' fill='none' stroke='%233F434B' stroke-width='2.2' stroke-linecap='round' stroke-linejoin='round'><path d='M6 9l6 6 6-6'/></svg>"); background-repeat:no-repeat; background-position:right 12px center; }
  .field input.inp, .field select.inp { border:1px solid var(--line); border-radius:var(--r-md); padding:9px 12px; font-family:var(--mono); font-size:15px; background:var(--surface); color:var(--ink); width:120px; text-align:right; }
  .field select.inp{ font-family:var(--sans); text-align:left; padding-right:34px; width:auto; min-width:132px; }
  .verify-bar{ display:flex; align-items:center; gap:12px; justify-content:center; background:var(--accent-weak); color:var(--ink); padding:9px 16px; font-size:15px; border-bottom:1px solid var(--line); flex-wrap:wrap; }
  .verify-bar .btn{ padding:6px 14px; }
  /* Settings/athlete-profile: every entry box the same width, text right-aligned */
  .set-grid .field .inp{ width:150px; text-align:right; }
  .toggle { width:40px; height:23px; border-radius:var(--r-xl); background:var(--line); position:relative; cursor:pointer; flex:none; transition:background .15s; }
  .toggle.on { background:var(--optimal); }
  .toggle::after { content:""; position:absolute; top:2px; left:2px; width:19px; height:19px; border-radius:50%; background:#fff; box-shadow:var(--shadow); transition:left .15s; }
  .toggle.on::after { left:19px; }
  /* ---- Connections grid ----
     Brand cards: the wordmark is the heading (a logotype already names the
     service), the status line under it is overwritten in place once the real
     state arrives, actions sit on the card's base line. The manual-upload row
     has no logotype, so it keeps a text title and runs full width. */
  .cx-grid { display:grid; grid-template-columns:repeat(2,1fr); gap:14px; }
  .cx-card { background:var(--surface); border:1px solid var(--line); border-radius:var(--r-lg); padding:20px 20px 16px; display:flex; flex-direction:column; gap:12px; transition:border-color .15s ease, box-shadow .15s ease; }
  .cx-card:hover { border-color:var(--muted); box-shadow:0 6px 18px rgba(20,24,32,.06); }
  .cx-mark { display:flex; align-items:center; min-height:34px; color:var(--ink); }
  .cx-title { font-weight:700; font-size:15px; margin-left:10px; }
  .cx-status { flex:1; font-size:15px; line-height:1.5; color:var(--muted); }
  /* The "can this receive a workout" sub-line. Sized off .cx-status above it,
     not off .note: .note is body size (15px), which rendered this 2px larger
     than the status it explains and made the connected cards look mismatched
     against the ones still showing their idle pitch. */
  .cx-send { font-size:15px; line-height:1.5; color:var(--faint); margin-top:4px; }
  .cx-actions { display:flex; gap:8px; align-items:center; flex-wrap:wrap; }
  .cx-card.cx-wide { grid-column:1 / -1; flex-direction:row; align-items:center; gap:16px; padding:14px 20px; }
  .cx-card.cx-wide .cx-status { flex:1; }
  .cx-note { font-size:15px; color:var(--faint); margin-top:10px; }
  @media (max-width:640px){ .cx-grid { grid-template-columns:1fr; } .cx-card.cx-wide { flex-direction:column; align-items:flex-start; gap:10px; } }

  .foot { margin-top:26px; text-align:center; color:var(--faint); font-size:15px; font-family:var(--mono); letter-spacing:.04em; }

  @media (max-width:1120px){ .col-3,.col-4,.col-5{grid-column:span 6} .col-7,.col-8,.col-9{grid-column:span 12} .stat-row{grid-template-columns:repeat(2,1fr)} .set-grid{grid-template-columns:1fr} }
  @media (max-width:760px){ .app{grid-template-columns:54px 1fr} .screen{padding:16px} .col-3,.col-4,.col-5,.col-6,.col-7{grid-column:span 12} .ad-metrics{grid-template-columns:repeat(2,1fr)} .topbar{flex-wrap:wrap} .topbar-right{width:100%;margin-left:0} .rail-word,.nav-label,.rail-user-name{display:none} .rail{padding:16px 6px;align-items:center} .nav-btn{justify-content:center;padding:0;gap:0} .rail-brand{justify-content:center;padding:0} }
  @media (prefers-reduced-motion:reduce){ *{transition:none!important} }

  /* Button system — reused by the auth + onboarding screens (the only landing-era CSS the app still needs). */
  .lp-btn{ border:0; border-radius:var(--r-md); padding:12px 20px; font-size:18px; font-weight:600; cursor:pointer; font-family:var(--sans); text-transform:uppercase; letter-spacing:var(--track-btn); }
  .lp-btn.primary{ background:var(--accent); color:#fff; }
  .lp-btn.primary:hover{ opacity:.92; }
  .lp-btn.pop{ background:var(--pop); color:var(--pop-ink); }
  .lp-btn.pop:hover{ filter:brightness(.96); }
  .lp-btn.ghost{ background:transparent; color:var(--ink); border:1px solid var(--line); }
  .lp-btn.big{ padding:14px 26px; font-size:18px; }

  /* ---- Auth ---- */
  /* The darkening scrim is a background layer, not a pseudo-element. As an absolutely
     positioned ::before it sat in the scrollable overflow and scrolled away with the
     content, while the photo behind it stayed pinned to the padding box: scroll a card
     that overflows a short phone screen and the bottom of the image came out from under
     the scrim, with a visible seam. As a layer it is painted with the photo and cannot
     drift from it. It also stops the scrim painting over a card that isn't positioned,
     which the ob-card was relying on luck to avoid. */
  .auth-back{ position:fixed; inset:0; display:grid; place-items:center; z-index:120; padding:24px; overflow-x:hidden; overflow-y:auto; max-width:100vw;
    background:linear-gradient(180deg, rgba(15,18,22,.68) 0%, rgba(15,18,22,.9) 100%), url(../img/hero-1.jpg) center/cover no-repeat #0f1216; }
  /* 100%, not 94vw: the width is measured inside .auth-back's own 24px padding, so a vw
     figure double-counts the gutter. On a 375px phone 94vw is 353px against a 327px
     content box, which pushed the card off the left padding and a pixel past the right
     edge, so it read as not centred. */
  .auth-wrap{ position:relative; z-index:1; display:flex; flex-direction:column; align-items:center; gap:16px; width:min(400px,100%); }
  .auth-brand{ display:flex; align-items:center; gap:11px; }
  .auth-brand .mk{ width:30px; height:30px; border-radius:var(--r-md); background:var(--accent); display:grid; place-items:center; }
  .auth-brand .mk svg{ width:18px; height:18px; }
  .auth-brand .wm{ font-family:var(--logo); text-transform:uppercase; letter-spacing:.42em; font-weight:700; font-size:22px; color:#fff; }
  .auth-tag{ margin-top:-6px; font-family:var(--mono); text-transform:uppercase; letter-spacing:var(--track-caps); font-size:13px; color:rgba(255,255,255,.62); }
  @keyframes authIn{ from{ opacity:0; transform:translateY(14px); filter:blur(8px); } to{ opacity:1; transform:none; filter:blur(0); } }
  .auth-brand,.auth-tag,.auth-card{ animation:authIn .85s cubic-bezier(.2,.7,.2,1) both; }
  .auth-tag{ animation-delay:.08s; } .auth-card{ animation-delay:.16s; }
  @media (prefers-reduced-motion: reduce){ .auth-brand,.auth-tag,.auth-card{ animation:none; } }
  .auth-card{ background:var(--surface); border:1px solid var(--line); border-radius:var(--r-xl); box-shadow:0 24px 64px rgba(0,0,0,.5); width:100%; padding:28px; }
  /* activities list — week-grouped */
  .al-controls { display:flex; align-items:center; gap:12px; flex-wrap:wrap; margin-bottom:18px; }
  .al-group { margin-bottom:22px; }
  .al-wk { display:flex; align-items:baseline; gap:12px; margin:0 2px 8px; flex-wrap:wrap; }
  .al-wk-t { font-size:var(--fs-subhead); font-weight:800; }
  .al-wk-s { font-size:var(--fs-caption); color:var(--muted); }
  .al-list { background:var(--surface); border:1px solid var(--line); border-radius:var(--r-lg); overflow:hidden; }
  .al-row { display:flex; align-items:center; gap:14px; padding:13px 16px; border-bottom:1px solid var(--line-2); cursor:pointer; transition:background .12s; }
  .al-row:last-child { border-bottom:0; }
  .al-row:hover { background:var(--inset); }
  .al-row:hover .al-title { color:var(--accent); }
  /* Sport tile: tinted rather than a solid block, so a list of twenty rows reads
     as a calm column with colour used for recognition, not for shouting. */
  .al-tile { width:44px; height:44px; border-radius:var(--r-lg); display:grid; place-items:center; flex:none; }
  .al-tile svg { width:21px; height:21px; }
  .al-main { flex:1; min-width:0; }
  .al-title { font-size:var(--fs-body); font-weight:700; white-space:nowrap; overflow:hidden; text-overflow:ellipsis; }
  .al-sub { font-size:var(--fs-caption); color:var(--muted); margin-top:2px; white-space:nowrap;
    overflow:hidden; text-overflow:ellipsis; }
  /* Effort leads, with a bar showing this session against the biggest in the list. */
  .al-effort { flex:none; width:104px; text-align:right; }
  .al-n { font-size:var(--fs-heading); font-weight:700; font-variant-numeric:tabular-nums; line-height:1.1; }
  .al-u { font-size:var(--fs-caption); color:var(--muted); font-weight:600; margin-left:5px; }
  .al-bar { display:block; height:4px; border-radius:3px; background:var(--line-2); margin-top:7px; overflow:hidden; }
  .al-bar i { display:block; height:100%; border-radius:3px; opacity:.85; }
  @media (max-width:760px){ .al-effort { width:74px; } .al-sub { white-space:normal; } }
  @media (max-width:640px){ .al-stats .al-s:nth-child(n+2){ display:none; } .al-controls #actSearch{ width:100%!important; } }
  /* onboarding wizard */
  .ob-card{ width:min(460px,100%); }   /* see .auth-wrap: inside .auth-back's padding */
  .ob-card h2{ margin:0; font-size:var(--fs-heading); font-weight:800; }
  .ob-dots{ display:flex; gap:6px; margin-bottom:20px; }
  .ob-dot{ height:4px; flex:1; border-radius:2px; background:var(--line); transition:background .2s; }
  .ob-dot.on{ background:var(--accent); }
  .ob-lab{ font-size:13px; text-transform:uppercase; letter-spacing:var(--track-caps); color:var(--muted); font-weight:600; margin-bottom:8px; }
  .ob-chips{ display:flex; gap:8px; flex-wrap:wrap; }
  .ob-chip{ padding:9px 15px; border:1px solid var(--line); background:var(--surface); border-radius:var(--r-pill); font-size:var(--fs-body); font-weight:600; color:var(--ink); cursor:pointer; }
  .ob-chip.on{ background:var(--ink); color:var(--surface); border-color:var(--ink); }
  .ob-field{ display:flex; align-items:center; gap:10px; }
  .ob-flab{ font-size:var(--fs-body); color:var(--muted); min-width:112px; }
  .ob-unit{ font-size:var(--fs-body); color:var(--muted); }
  .ob-foot{ display:flex; align-items:center; gap:10px; margin-top:26px; }
  .ob-brands{ text-align:center; color:var(--faint); font-size:13px; font-weight:600; letter-spacing:var(--track-caps); text-transform:uppercase; margin:0 0 16px; }
  /* "Choose a Connection": the brand marks alone, as tiles. These are wordmarks, so the
     logo already carries the name; a text label beside it would just say it twice.
     Auto-fit rather than a fixed column count, so five tiles reflow instead of leaving
     an orphan on its own row on a narrow phone. */
  /* dense: the double-width tile needs a whole row, which otherwise strands a
     single-width tile beside a hole. Dense backfills that gap with the next tile
     that fits, so the grid closes up at both two and three columns. */
  .ob-conns{ display:grid; grid-template-columns:repeat(auto-fit,minmax(120px,1fr)); grid-auto-flow:row dense; gap:10px; }
  .ob-conn{ display:flex; align-items:center; justify-content:center; min-height:76px; padding:14px 16px; border:1px solid var(--line); border-radius:var(--r-lg); background:var(--surface); cursor:pointer; font-family:var(--sans); }
  .ob-conn:hover{ border-color:var(--ink-2); }
  .ob-conn:focus-visible{ outline:2px solid var(--accent); outline-offset:2px; }
  /* brand.ts sets each mark's height inline, tuned for a settings row. Inline wins over
     a stylesheet, so capping width here squashed the wide marks instead of scaling them:
     Hammerhead is 1399x120, about 11.7:1, so at an 18px height it wants 210px and was
     being crushed into ~90px. !important hands sizing back to the intrinsic ratio, and
     the caps then bound it on whichever axis runs out first. */
  .ob-conn-mark{ display:flex; align-items:center; justify-content:center; max-width:100%; }
  .ob-conn-mark img,.ob-conn-mark svg{ width:auto !important; height:auto !important; max-width:100%; max-height:30px; display:block; }
  /* A mark past about 8:1 cannot be read in a one-column tile without shrinking to a
     hairline, so it takes two. Five tiles then sit 3 + 2 instead of leaving an orphan. */
  .ob-conn.is-wide{ grid-column:span 2; }
  /* first-run product tour */
  /* touch-action:none stops a touch-scroll from dragging the page out from under
     the fixed spotlight, which detached the highlight from its feature on mobile.
     The tour's own scrollIntoView between steps is programmatic and unaffected. */
  #tourHost{ position:fixed; inset:0; z-index:400; touch-action:none; }
  .tour-spot{ position:fixed; }
  /* The popup keeps its own scroll if it is taller than a small screen. */
  .tour-pop{ position:fixed; width:320px; max-width:calc(100vw - 16px); background:var(--surface); border:1px solid var(--line); border-radius:var(--r-lg); box-shadow:var(--shadow-pop); padding:18px 18px 16px; z-index:401; touch-action:auto; overscroll-behavior:contain; max-height:calc(100vh - 16px); overflow:auto; }
  .tour-pop .tour-step{ font-size:13px; color:var(--faint); font-weight:600; letter-spacing:var(--track-caps); text-transform:uppercase; margin-bottom:7px; }
  .tour-pop h3{ margin:0 0 6px; font-size:18px; font-weight:800; color:var(--ink); }
  .tour-pop p{ margin:0; font-size:15px; color:var(--ink-2); line-height:1.55; }
  .tour-actions{ display:flex; align-items:center; gap:8px; margin-top:16px; }
  /* Invite eyebrow: micro-label tier (13/600, tracked caps), so the /join card says why
     it is showing a signup form the rest of the site does not offer. */
  .auth-invite{ font-size:13px; font-weight:600; text-transform:uppercase; letter-spacing:var(--track-caps); color:var(--accent); margin:0 0 8px; }
  .auth-card h2{ margin:0 0 4px; font-size:22px; font-weight:700; letter-spacing:-.01em; }
  .auth-card .sub{ font-size:18px; color:var(--muted); margin-bottom:20px; }
  .auth-field{ margin-bottom:14px; }
  .auth-field label{ display:block; font-size:15px; color:var(--ink-2); margin-bottom:6px; }
  .auth-field input{ width:100%; border:1px solid var(--line); border-radius:var(--r-md); padding:11px 13px; font-size:15px; font-family:var(--sans); background:var(--surface); color:var(--ink); }
  .auth-field input:focus{ outline:none; border-color:var(--accent); }
  /* The .lp-btn is sized for a landing hero; scale it down inside the auth/onboarding card. */
  .auth-card .lp-btn{ font-size:15px; padding:11px 18px; }
  .auth-switch{ text-align:center; font-size:15px; color:var(--muted); margin-top:16px; }
  .auth-switch a{ color:var(--accent); cursor:pointer; font-weight:600; }
  .auth-consent{ display:flex; gap:10px; align-items:flex-start; margin:2px 0 4px; font-size:15px; line-height:1.45; color:var(--muted); cursor:pointer; }
  .auth-consent input{ flex:0 0 auto; width:17px; height:17px; margin-top:1px; accent-color:var(--accent); cursor:pointer; }
  .auth-consent a{ color:var(--accent); font-weight:600; }

/* ===== Activity review v3 ===== */
.ad-page{ }
/* hero band */
.ad-hero{ display:flex; flex-wrap:wrap; background:var(--surface); border:1px solid var(--line); border-radius:var(--r-xl); padding:22px 10px; margin-bottom:16px; }
.ad-hero-item{ flex:1; min-width:118px; padding:2px 22px; border-left:1px solid var(--line); display:flex; flex-direction:column; gap:6px; }
.ad-hero-item:first-child{ border-left:0; }
.ad-hero .hv{ font-size:30px; font-weight:800; color:var(--ink); letter-spacing:-.02em; line-height:1; font-variant-numeric:tabular-nums; }
.ad-hero .hu{ font-size:15px; font-weight:600; color:var(--muted); margin-left:4px; letter-spacing:0; }
.ad-hero .hk{ font-size:13px; text-transform:uppercase; letter-spacing:var(--track-caps); color:var(--muted); font-weight:600; }
/* detail metrics list */
.ad-details .ad-dl{ display:grid; grid-template-columns:repeat(3,1fr); gap:0 30px; }
.ad-di{ display:flex; justify-content:space-between; align-items:baseline; padding:11px 2px; border-bottom:1px solid var(--line); }
.ad-di .dk{ font-size:15px; color:var(--muted); }
.ad-di .dv{ font-size:15px; font-weight:700; color:var(--ink); font-variant-numeric:tabular-nums; }
.ad-di.click{ cursor:pointer; }
.ad-di.click .dk{ text-decoration:underline dotted var(--faint); text-underline-offset:3px; }
.ad-di.click:hover .dk{ color:var(--ink); }

/* chart card */
.ad-chart-card{ padding:14px 16px 12px; }
.ad-chart-head{ display:flex; align-items:center; gap:12px; flex-wrap:wrap; margin-bottom:10px; }
.ad-zoomhint{ font-size:15px; color:var(--faint); font-weight:600; }
.ad-tools{ margin-left:auto; display:flex; align-items:center; gap:8px; }
/* .ad-xtoggle and .cmp-tabs were two more segmented controls with their own
   radii and sizes. Both now render as .seg; these aliases only exist so any
   stray markup keeps working rather than falling back to unstyled buttons. */
.ad-xtoggle{ display:inline-flex; background:var(--inset); border:1px solid var(--line); border-radius:var(--r-md); padding:3px; gap:2px; }
.ad-xtoggle button{ border:0; background:transparent; color:var(--muted); font-family:var(--sans); font-size:13px;
  font-weight:700; letter-spacing:var(--track-btn); padding:7px 14px; border-radius:var(--r-sm); cursor:pointer; }
.ad-xtoggle button.on{ background:var(--ink); color:#fff; }
.ad-zoombtns{ display:flex; border:1px solid var(--line); border-radius:var(--r-sm); overflow:hidden; }
.ad-zoombtns button{ border:0; background:var(--surface); color:var(--muted); width:30px; height:30px; cursor:pointer; font-size:18px; line-height:1; }
.ad-zoombtns button:hover{ background:#fafafa; color:var(--ink); }
.ad-reset{ border:1px solid var(--line); background:var(--surface); border-radius:var(--r-sm); padding:6px 11px; font-size:13px; font-weight:600; color:var(--ink-2); cursor:pointer; }
.ad-reset:hover{ border-color:var(--accent); color:var(--accent); }
.ad-menu-wrap{ position:relative; }
.ad-menu-btn{ display:inline-flex; align-items:center; gap:7px; border:1px solid var(--line); background:var(--surface); border-radius:var(--r-sm); padding:6px 12px; font-size:13px; font-weight:600; color:var(--ink-2); cursor:pointer; }
.ad-menu-btn svg{ width:12px; height:12px; }
.ad-menu{ position:absolute; right:0; top:38px; z-index:30; background:var(--surface); border:1px solid var(--line); border-radius:var(--r-lg); box-shadow:0 18px 44px rgba(0,0,0,.16); padding:6px; min-width:196px; }
.ad-menu[hidden]{ display:none; }
.ad-menu-item{ display:flex; align-items:center; gap:9px; padding:8px 10px; border-radius:var(--r-sm); font-size:15px; color:var(--ink); cursor:pointer; user-select:none; }
.ad-menu-item:hover{ background:#fafafa; }
.ad-menu-item i{ width:9px; height:9px; border-radius:50%; }
.ad-menu-item input{ margin:0; accent-color:var(--accent); cursor:pointer; }

/* readout */
.ad-readout{ display:flex; align-items:center; gap:16px; flex-wrap:wrap; padding:10px 13px; background:#fafafa; border:1px solid var(--line); border-radius:var(--r-md); margin-bottom:10px; min-height:44px; }
.ad-readout .ro-x{ font-size:18px; font-weight:800; color:var(--ink); font-variant-numeric:tabular-nums; min-width:74px; }
.ad-ro-metric{ display:flex; flex-direction:column; line-height:1.15; }
.ad-ro-metric .rk{ font-size:13px; letter-spacing:var(--track-caps); text-transform:uppercase; color:var(--muted); font-weight:600; display:flex; align-items:center; gap:5px; }
.ad-ro-metric .rk i{ width:8px; height:8px; border-radius:50%; }
.ad-ro-metric .rv{ font-size:18px; font-weight:700; color:var(--ink); font-variant-numeric:tabular-nums; }
.ad-hint{ color:var(--faint); font-weight:600; font-size:15px; }

/* stack + lanes */
.ad-stack{ position:relative; cursor:crosshair; user-select:none; }
/* A dedicated label band above each trace so the metric name + live value never
   sit on top of the data (they used to overlay the trace with a translucent bg). */
/* No CSS border between lanes: each lane's SVG already draws a 1px baseline at its
   own bottom (the trace floor), and a border-top here sat 1px below that baseline,
   reading as a doubled divider. The baseline alone is the divider now. */
.ad-lane{ position:relative; padding-top:22px; }
.ad-lane.off{ display:none; }
/* The label floats over the trace, so it needs its own ground: with no
   background the chart line ran straight through the text and the metric name
   became unreadable exactly when you were scrubbing and the live value made the
   label longest. Translucent rather than solid so the trace still ghosts
   through instead of a white block punched out of the data. */
.ad-lane-label{ position:absolute; top:3px; left:2px; z-index:3; font-size:13px; letter-spacing:var(--track-caps); text-transform:uppercase; font-weight:600; color:var(--muted); pointer-events:none; display:flex; align-items:center; gap:5px; }
.ad-lane-label i{ width:8px; height:8px; border-radius:50%; }
.ad-lane-label .llv{ color:var(--ink); font-weight:800; margin-left:4px; }
/* Faint min/max reference values at the lane edge - a light Y-axis read without
   the density of a full axis. */
.ad-lane-ax{ position:absolute; right:5px; z-index:2; font:600 13px/1 var(--mono); color:var(--faint); opacity:.72; pointer-events:none; font-variant-numeric:tabular-nums; }
.ad-lane-ax.ax-hi{ top:24px; }
.ad-lane-ax.ax-lo{ bottom:3px; }
/* ===== overlay chart widget (all metrics on one plot) ===== */
.ov-chips{ display:flex; flex-wrap:wrap; gap:8px; margin-bottom:14px; }
.ov-chip{ display:inline-flex; align-items:center; gap:6px; border:1px solid var(--line); background:var(--surface); border-radius:var(--r-xl); padding:5px 12px; font-size:13px; font-weight:600; color:var(--ink-2); cursor:pointer; }
.ov-chip:hover{ border-color:var(--muted); }
.ov-chip i{ width:9px; height:9px; border-radius:50%; flex:none; }
.ov-chip.off{ opacity:.42; }
.ov-chip.off i{ background:var(--line) !important; }
.ov-wrap{ display:flex; align-items:stretch; gap:9px; }
.ov-yax{ display:flex; gap:10px; }
.ov-ax{ display:flex; flex-direction:column; justify-content:space-between; height:280px; font:600 13px/1 var(--mono); font-variant-numeric:tabular-nums; white-space:nowrap; }
.ov-yax.ov-l .ov-ax{ text-align:right; align-items:flex-end; }
.ov-plot{ position:relative; flex:1; min-width:0; border-left:1px solid var(--line); border-bottom:1px solid var(--line); cursor:crosshair; }
.ov-plot svg{ display:block; width:100%; }
.ov-cross{ position:absolute; top:0; width:1px; background:var(--ink); opacity:0; pointer-events:none; transition:opacity .1s; }
.ov-read{ display:flex; flex-wrap:wrap; align-items:center; gap:10px 18px; min-height:22px; margin-bottom:12px; font-size:15px; }
.ov-xax{ display:flex; justify-content:space-between; margin-top:7px; font:600 13px/1 var(--mono); color:var(--faint); font-variant-numeric:tabular-nums; }
.ad-lane svg{ display:block; width:100%; }
.ad-lane .expand{ position:absolute; top:3px; right:6px; z-index:3; cursor:pointer; color:var(--faint); font-size:15px; opacity:0; transition:opacity .12s; }
.ad-lane:hover .expand{ opacity:1; }
.ad-dot{ position:absolute; width:9px; height:9px; border-radius:50%; border:2px solid #fff; box-shadow:0 0 0 1px rgba(0,0,0,.15); transform:translate(-50%,-50%); pointer-events:none; z-index:4; opacity:0; }
.ad-cross{ position:absolute; top:0; width:1px; background:var(--ink); opacity:0; pointer-events:none; z-index:2; }
.ad-band{ position:absolute; top:0; background:rgba(255,23,68,.10); border-left:1px solid var(--accent); border-right:1px solid var(--accent); pointer-events:none; z-index:1; display:none; }
.ad-sel{ position:absolute; top:0; bottom:0; background:rgba(15,17,20,.07); border-left:1px solid var(--ink); border-right:1px solid var(--ink); pointer-events:none; z-index:5; display:none; }

/* zones */
.ad-zone{ display:flex; align-items:center; gap:10px; margin-bottom:9px; }
.ad-zone .zl{ width:22px; flex:0 0 auto; white-space:nowrap; font-size:13px; font-weight:700; color:var(--muted); }
.ad-zone.named .zl{ width:76px; }
/* The athlete's own boundary for each zone, between the label and the bar.
   Fixed width + tabular mono so seven rows of ranges read as one column. */
.ad-zone .zr{ flex:0 0 auto; width:60px; font-family:var(--mono); font-size:13px; color:var(--faint); font-variant-numeric:tabular-nums; white-space:nowrap; }
.ad-zone .zbar{ flex:1; height:9px; border-radius:var(--r-sm); background:var(--line); overflow:hidden; }
.ad-zone .zbar span{ display:block; height:100%; border-radius:var(--r-sm); }
.ad-zone .zt{ font-size:13px; color:var(--ink-2); font-weight:600; font-variant-numeric:tabular-nums; min-width:64px; text-align:right; }

/* training status */
.ts-head{ display:flex; align-items:center; gap:8px; margin-bottom:10px; }
.ts-badge{ font-size:13px; font-weight:800; letter-spacing:.05em; text-transform:uppercase; padding:5px 11px; border-radius:var(--r-xl); white-space:nowrap; }
.ts-metrics{ display:grid; grid-template-columns:repeat(3,1fr); gap:1px; background:var(--line-2); border:1px solid var(--line); border-radius:var(--r-md); overflow:hidden; margin:10px 0; }
.ts-metrics .tm{ background:var(--surface); padding:9px 11px; }
.ts-metrics .tm .k{ font-size:13px; text-transform:uppercase; letter-spacing:var(--track-caps); color:var(--muted); font-weight:600; }
.ts-metrics .tm .v{ font-size:18px; font-weight:800; color:var(--ink); font-variant-numeric:tabular-nums; }
/* Phone: a label that wraps to two lines (e.g. "7-day effort") shouldn't shove its
   value out of line with its neighbours -- pin values to the bottom of each cell. */
@media (max-width:520px){
  .ts-metrics .tm{ display:flex; flex-direction:column; }
  .ts-metrics .tm .v{ margin-top:auto; }
}

/* modal */
.ad-modal-back{ position:fixed; inset:0; background:rgba(15,17,20,.5); z-index:100; display:grid; place-items:center; padding:24px; }
.ad-modal{ background:var(--surface); border-radius:var(--r-xl); width:min(560px,100%); max-height:86vh; overflow:auto; padding:22px 24px; box-shadow:0 30px 80px rgba(0,0,0,.3); }
.ad-modal h3{ font-size:22px; font-weight:800; margin:0; }
.ad-modal .mclose{ float:right; cursor:pointer; color:var(--muted); font-size:22px; line-height:1; }
.ad-stats{ display:grid; gap:1px; background:var(--line-2); border:1px solid var(--line); border-radius:var(--r-lg); overflow:hidden; }
.ad-stats .ad-stat{ background:var(--surface); padding:11px 13px; }
.ad-stats .ad-stat .k{ font-size:13px; letter-spacing:var(--track-caps); text-transform:uppercase; color:var(--muted); font-weight:600; }
.ad-stats .ad-stat .v{ font-size:18px; font-weight:800; color:var(--ink); font-variant-numeric:tabular-nums; }
.ad-stats .ad-stat .v small{ font-size:13px; color:var(--muted); font-weight:600; }
.ad-histo{ display:flex; align-items:flex-end; gap:2px; height:150px; margin:16px 0; }
.ad-histo .hb{ flex:1; background:var(--accent); border-radius:3px 3px 0 0; min-height:1px; }


/* ===== sidebar labels, tooltips, sport icons, font scale ===== */
.rail-brand{ display:flex; align-items:center; gap:10px; margin-bottom:14px; padding:0 12px; cursor:pointer; }
.rail-brand .logo{ margin-bottom:0; }
.rail-logo{ width:34px; height:34px; border-radius:50%; display:block; flex:0 0 auto; }
.rail-word{ font-family:var(--logo); font-style:italic; font-weight:600; letter-spacing:-.02em; font-size:22px; color:var(--ink); }
.nav-btn{ width:100%; height:42px; display:flex; align-items:center; justify-content:flex-start; gap:12px; padding:0 12px; }
.nav-ic{ display:grid; place-items:center; width:22px; height:22px; flex:none; }
.nav-ic svg{ width:20px; height:20px; }
.nav-label{ font-size:15px; font-weight:600; white-space:nowrap; overflow:hidden; text-overflow:ellipsis; color:inherit; }
.rail-user{ display:flex; align-items:center; gap:10px; padding:8px; margin-top:2px; cursor:pointer; border-radius:var(--r-md); }
.rail-user:hover{ background:#f6f7f9; }
.rail-user .avatar{ margin-top:0; flex:none; }
.rail-user-name{ font-size:15px; font-weight:600; color:var(--ink); white-space:nowrap; overflow:hidden; text-overflow:ellipsis; }
/* vertical-align:middle centres on the lowercase x-height, but these labels are
   uppercase, so the badge reads slightly low against the caps - nudge it up ~1px
   to sit on the cap middle. The glyph itself is flex-centred in the circle. */
.itip{ display:inline-flex; align-items:center; justify-content:center; width:16px; height:16px; border-radius:50%; border:1px solid var(--line); color:var(--muted); font-size:13px; font-weight:700; line-height:1; margin-left:5px; cursor:help; position:relative; top:-1px; vertical-align:middle; text-align:center; }
.itip .itip-pop{ position:fixed; left:0; top:0; transform:translate(-50%,calc(-100% - 9px)); width:232px; background:var(--ink); color:#fff; font-size:15px; font-weight:500; line-height:1.5; text-transform:none; letter-spacing:0; text-align:left; padding:10px 12px; border-radius:var(--r-md); opacity:0; pointer-events:none; transition:opacity .12s; z-index:400; box-shadow:0 14px 34px rgba(0,0,0,.26); }
.itip:hover .itip-pop, .itip:focus .itip-pop{ opacity:1; }
.fchip-ic{ display:inline-flex; align-items:center; margin-right:1px; }
.fchip-ic svg{ width:15px; height:15px; }
.zdot{ display:inline-block; width:9px; height:9px; border-radius:50%; margin-right:8px; vertical-align:middle; }
/* activity page: heading / body / label (3 sizes) */
.ad-hero .hv{ font-size:22px; }
.ad-hero .hu, .ad-hero .hk, .ad-lane-label, .ad-ro-metric .rk, .ad-zone .zl, .ad-zone .zt, .ts-metrics .k{ font-size:13px; }
.ad-di .dk, .ad-di .dv, .ad-ro-metric .rv, .ad-readout .ro-x, .ad-menu-item, .ad-menu-btn, .ad-xtoggle button, .ad-reset, .ad-zoombtns button, .ad-zoomhint, .ts-metrics .v{ font-size:15px; }


/* session analysis */
.ad-analysis .ad-an-head{ display:flex; align-items:flex-start; gap:12px; margin-bottom:14px; }
.ad-an-badge{ font-size:13px; font-weight:800; letter-spacing:.05em; padding:5px 11px; border-radius:var(--r-xl); white-space:nowrap; flex:none; }
.ad-an-focus{ font-size:15px; color:var(--ink-2); margin-top:3px; }
.ad-an-tiles{ display:grid; gap:1px; background:var(--line-2); border:1px solid var(--line); border-radius:var(--r-lg); overflow:hidden; margin-bottom:14px; }
.ad-an-tile{ background:var(--surface); padding:11px 13px; }
.ad-an-tile .k{ font-size:13px; text-transform:uppercase; letter-spacing:var(--track-caps); color:var(--muted); font-weight:600; }
.ad-an-tile .v{ font-size:15px; font-weight:800; color:var(--ink); margin-top:2px; }
.ad-an-text{ font-size:15px; line-height:1.6; color:var(--ink-2); margin:0 0 14px; }
.ad-an-bar{ display:flex; height:10px; border-radius:var(--r-sm); overflow:hidden; }
.ad-an-bar span{ display:block; height:100%; }
.ad-an-legend{ display:flex; gap:18px; margin-top:8px; font-size:15px; color:var(--muted); font-weight:600; }
.ad-an-legend i{ display:inline-block; width:9px; height:9px; border-radius:50%; margin-right:6px; vertical-align:middle; }


/* dashboard weekly-load bars */
.wlb{ display:flex; align-items:flex-end; gap:12px; height:100%; min-height:150px; width:100%; }
/* side-by-side widget cards stretch to equal height (no gap below the shorter one) */
.w-grid[data-sfc="dash"] .widget > .w-inner{ height:100%; }
.w-grid[data-sfc="dash"] .widget > .w-inner > .card{ height:100%; }
/* same equal-height stretch on the activity page so short cards fill their row (no gap below) */
.w-grid[data-sfc="act"] .widget > .w-inner{ height:100%; }
.w-grid[data-sfc="act"] .widget > .w-inner > .card{ height:100%; }
/* the Metrics table spans the height of the two stacked right-rail cards
   (training status + how it went), so those flow into the column beside it
   and together match the Metrics height exactly */
.w-grid[data-sfc="act"] [data-wtype="a_metrics"]{ grid-row:span 2; }
@media (max-width:1120px){ .w-grid[data-sfc="act"] [data-wtype="a_metrics"]{ grid-row:auto; } }
/* uniform spacing between every block: rely on the grid gap, drop per-card margins */
.w-grid[data-sfc="act"] .widget > .w-inner > *{ margin-top:0 !important; margin-bottom:0 !important; }
/* clean metric table: no doubled line where the last-column cell border meets the table frame */
.cg.cgact .cg-cell:nth-child(4n){ border-right:0; }
/* Row-end border removal for the SIX-column dashboard grid only. This used
   to be .cg:not(.act), but activity grids are classed cgact, not act, so the
   rule leaked into them and deleted the border after every 6th tile -- which
   in the default layouts sat exactly between Avg HR and Max HR on rides and
   between Cadence and Stride Length on runs. Reported as 'put a line between
   x and y'; the line was never supposed to be missing. */
.cg.dash .cg-cell:nth-child(6n){ border-right:0; }
.wlb-col{ flex:1; display:flex; flex-direction:column; align-items:center; height:100%; }
.wlb-track{ flex:1; width:100%; display:flex; align-items:flex-end; justify-content:center; min-height:0; }
.wlb-bar{ width:62%; max-width:36px; border-radius:6px 6px 0 0; overflow:hidden; display:flex; flex-direction:column-reverse; min-height:3px; background:var(--line); }
.wlb-bar span{ display:block; width:100%; }
.wlb-lab{ font-size:13px; color:var(--muted); margin-top:7px; font-weight:600; }
.wlb-val{ font-size:13px; color:var(--ink); font-weight:700; }
.wlb-leg{ font-size:13px; color:var(--muted); font-weight:600; margin-left:14px; }
.wlb-leg i{ display:inline-block; width:9px; height:9px; border-radius:50%; margin-right:5px; vertical-align:middle; }
/* hover breakdown tooltip for the weekly trend bars (HR/power zones, elevation) */
.wlb-tip{ display:none; }
.wlb-col:has(.wlb-tip){ cursor:default; }
.wlb-col:has(.wlb-tip):hover .wlb-bar{ filter:brightness(1.08); }
.wlb-tt{ position:fixed; z-index:1000; pointer-events:none; background:var(--surface); border:1px solid var(--line); border-radius:10px; box-shadow:var(--shadow-pop); padding:9px 11px; min-width:136px; }
.wlb-tt .tt-h{ font-family:var(--mono); font-size:13px; letter-spacing:var(--track-caps); text-transform:uppercase; color:var(--muted); font-weight:600; margin-bottom:6px; }
.wlb-tt .tt-r{ display:flex; align-items:center; justify-content:space-between; gap:16px; margin:3px 0; font-size:15px; }
.wlb-tt .tt-r span{ display:inline-flex; align-items:center; gap:7px; color:var(--ink-2); }
.wlb-tt .tt-r i{ width:9px; height:9px; border-radius:50%; display:inline-block; flex:none; }
.wlb-tt .tt-r b{ font-variant-numeric:tabular-nums; font-weight:700; color:var(--ink); }
.wlb-tt .tt-tot{ margin-top:5px; padding-top:5px; border-top:1px solid var(--line-2); }


/* wellness preview grid */
.well-group{ margin-top:14px; }
.well-gh{ font-size:13px; text-transform:uppercase; letter-spacing:var(--track-caps); color:var(--muted); font-weight:600; margin-bottom:8px; }


/* customizable field grids */
/* Uniform 1px border: the container draws EVERY outer edge, so the rounded
   corners render cleanly (a border missing on one side made border-radius notch
   the bottom corners). Internal grid lines come from the cells' own borders, and
   the edge-of-grid cell borders are dropped (see below) so they never double the
   container's. */
.cg{ display:grid; gap:0; background:var(--surface); border:1px solid var(--line); border-radius:var(--r-lg); overflow:hidden; grid-template-columns:repeat(6,1fr); }
.cg.cgact{ grid-template-columns:repeat(4,1fr); }
/* Horizontal separators are drawn as each cell's border-TOP (not border-bottom):
   the bottom edge is then purely the container's border, so a full last row never
   doubles it. First-row cells drop the top border (below) to avoid doubling the
   container's border-top -- mirroring how last-column cells drop border-right. */
.cg-cell{ background:var(--surface); padding:12px 14px; position:relative; border-right:1px solid var(--line); border-top:1px solid var(--line); align-self:stretch; }
/* Scoped by width because the column count -- and thus which cells form the first
   row -- changes at the mobile breakpoint (6/4 cols -> 2). */
@media (min-width:761px){
  .cg.dash .cg-cell:nth-child(-n+6){ border-top:0; }
  .cg.cgact .cg-cell:nth-child(-n+4){ border-top:0; }
}
.cg-fill{ background:var(--surface); }
.cg-cell .k{ font-size:13px; text-transform:uppercase; letter-spacing:var(--track-caps); color:var(--muted); font-weight:600; }
.cg-cell .v{ font-size:15px; font-weight:800; color:var(--ink); margin-top:3px; font-variant-numeric:tabular-nums; }
.cg-cell .v small{ font-size:13px; color:var(--muted); font-weight:600; }
.cg.editing .cg-cell{ cursor:grab; }
.cg-cell.drag-over{ outline:2px dashed var(--accent); outline-offset:-2px; }
.cg-x{ position:absolute; top:5px; right:6px; cursor:pointer; color:var(--faint); font-size:18px; line-height:1; width:17px; height:17px; text-align:center; border-radius:50%; }
.cg-x:hover{ background:var(--accent); color:#fff; }
.cg-add{ background:#fafafa; padding:11px 13px; display:flex; align-items:center; justify-content:center; color:var(--accent); font-weight:700; font-size:15px; cursor:pointer; }
/* Small controls that were clickable but visually inert. */
.link:hover{ text-decoration:underline; }
.cg-editbtn{ cursor:pointer; transition:color .14s ease; }
.cg-editbtn:hover{ color:var(--accent); }
.ob-chip{ transition:border-color .14s ease, color .14s ease; }
.ob-chip:hover{ border-color:var(--ink); }
.w-sz:hover, .ad-menu-btn:hover{ color:var(--ink); }
.rail-brand:hover{ opacity:.8; }
.cg-add:hover{ background:var(--surface); }
.cg-editbtn{ font-size:15px; font-weight:700; color:var(--accent); cursor:pointer; }
.cg-menu{ position:fixed; z-index:120; background:var(--surface); border:1px solid var(--line); border-radius:var(--r-lg); box-shadow:0 16px 40px rgba(0,0,0,.18); padding:6px; max-height:340px; overflow-y:auto; overscroll-behavior:contain; min-width:210px; }
.cg-menu div{ padding:8px 10px; border-radius:var(--r-sm); font-size:15px; cursor:pointer; color:var(--ink); }
.cg-menu div:hover{ background:#fafafa; }
/* compare view */
.cmp-ctrls{ display:flex; align-items:center; gap:10px; flex-wrap:wrap; }
.cmp-lab{ font-size:15px; color:var(--muted); font-weight:600; }
.cmp-r{ margin-left:auto; font-weight:800; color:var(--ink); font-variant-numeric:tabular-nums; }
.cmp-note{ font-size:15px; color:var(--ink-2); margin-top:10px; }
.cmp-ctrls .inp{ padding:9px 12px; padding-right:34px; }
.cmp-rel-list{ display:flex; flex-direction:column; gap:6px; }
.cmp-rel{ display:flex; align-items:center; gap:12px; text-align:left; background:var(--inset); border:1px solid transparent; border-radius:var(--r-sm); padding:9px 13px; cursor:pointer; font:inherit; color:var(--ink-2); }
.cmp-rel:hover{ border-color:var(--line); }
.cmp-rel.on{ border-color:var(--accent); background:var(--surface); color:var(--ink); }
.cmp-rel-txt{ flex:1; font-size:15px; }
.cmp-rel-r{ font-size:13px; color:var(--muted); font-weight:700; font-variant-numeric:tabular-nums; white-space:nowrap; }
.cmp-cols{ display:grid; grid-template-columns:1fr 1fr; gap:14px; }
.cmp-exp .cmp-side-lab{ margin-bottom:7px; }
.cmp-exp-text{ font-size:15px; line-height:1.6; color:var(--ink-2); margin:0; }
/* Both reads sit in one row, so they stretch to a shared height. One side having
   a session file and the other not should not leave half the row empty. */
.cmp-cols{ align-items:stretch; }
.cmp-cols .cmp-exp{ display:flex; flex-direction:column; height:100%; }
.cmp-pick .cmp-side-lab{ font-family:var(--sans); font-size:18px; letter-spacing:-.01em; text-transform:none; font-weight:700; color:var(--ink); margin-bottom:8px; }
.cmp-tbl td:first-child{ color:var(--muted); }
.cmp-tbl td.num{ font-weight:700; }
.cmp-tabs button{ padding:8px 16px; }   /* .seg, slightly roomier for the top-level modes */
/* The mode control (Compare / Records) is tabs on desktop and a dropdown on a phone:
   three long labels overrun 375px, and a native picker beats scrolling a tab bar. */
.seg-sel{ display:none; }
@media (max-width:520px){
  .cmp-tabs.seg-tabs{ display:none; }
  .seg-sel{ display:block; width:100%; margin-bottom:18px; }
}
@media(max-width:760px){ .cmp-cols{ grid-template-columns:1fr; } }


.cg-cell.cg-dragging{ opacity:.55; outline:2px solid var(--accent); outline-offset:-2px; z-index:5; }
.cg.editing .cg-cell{ cursor:grab; }
.cg.editing .cg-cell:active{ cursor:grabbing; }
.cg-hint{ font-size:15px; color:var(--faint); font-weight:600; }


/* widget layout engine */
.w-toolbar{ display:flex; justify-content:flex-end; align-items:center; gap:10px; margin:14px 0 8px; }
.w-hint{ font-size:15px; color:var(--faint); font-weight:600; margin-right:auto; }
.widget{ position:relative; min-width:0; }
.w-grid.editing .widget{ outline:1px dashed var(--line); outline-offset:-1px; border-radius:var(--r-xl); }
.w-grid.editing .w-inner{ pointer-events:none; }
.widget.w-dragging{ opacity:.6; outline:2px solid var(--accent); z-index:5; }
/* No text selection while reordering widgets or metric fields (a touch-drag on a
   phone was highlighting the card text instead of moving it). The grip drag runs
   outside "editing" mode, so the static rules below aren't enough on their own:
   the drag handlers add .reordering to <body> for the duration of a drag, and
   iOS only honours the -webkit- form for touch selection. */
.w-grid.editing, .w-grid.editing .widget, .w-grip, .cg.editing, .cg.editing .cg-cell{ -webkit-user-select:none; user-select:none; -webkit-touch-callout:none; }
body.reordering, body.reordering *{ -webkit-user-select:none !important; user-select:none !important; -webkit-touch-callout:none !important; }
.w-bar{ position:absolute; top:6px; right:6px; left:6px; display:flex; align-items:center; gap:8px; background:var(--ink); color:#fff; border-radius:var(--r-md); padding:5px 9px; z-index:6; font-size:13px; box-shadow:0 6px 18px rgba(0,0,0,.2); }
.w-bar .w-title{ font-weight:700; white-space:nowrap; overflow:hidden; text-overflow:ellipsis; }
.w-grip{ cursor:grab; font-size:15px; }
.w-sz{ background:rgba(255,255,255,.18); padding:2px 7px; border-radius:var(--r-sm); cursor:pointer; font-weight:700; }
.w-rm{ cursor:pointer; font-size:18px; line-height:1; padding:0 3px; }
.w-rm:hover{ color:var(--accent); }
.wpal{ display:grid; grid-template-columns:1fr 1fr; gap:8px; }
.wpal-item{ border:1px solid var(--line); border-radius:var(--r-md); padding:11px 12px; font-size:15px; font-weight:600; cursor:pointer; display:flex; justify-content:space-between; align-items:center; }
.wpal-item:hover{ border-color:var(--accent); color:var(--accent); }
.wpal-used{ font-size:13px; color:var(--muted); font-weight:700; }
.cc-ctrls{ display:flex; align-items:center; gap:8px; flex-wrap:wrap; }
.cc-ctrls .inp{ padding:8px 12px; width:auto; padding-right:32px; }
/* Custom Chart builder */
.cc-head{ display:flex; align-items:center; gap:10px; flex-wrap:wrap; margin-bottom:12px; }
.cc-seg button{ padding:6px 13px; }
.cc-filters{ display:inline-flex; gap:8px; margin-left:auto; }   /* sport + range, pushed to the right, wrapping together */
.cc-foot{ margin-top:9px; min-height:16px; font-size:15px; color:var(--muted); display:flex; gap:16px; align-items:center; flex-wrap:wrap; }
.cc-foot b{ color:var(--ink); font-weight:700; }
.cc-legend{ display:inline-flex; gap:12px; flex-wrap:wrap; }
.cc-legend span{ display:inline-flex; align-items:center; }
.cc-legend i{ width:9px; height:9px; border-radius:50%; display:inline-block; margin-right:5px; }
/* Calories Burned widget */
.kc-trace{ position:relative; }
.kc-tip{ position:absolute; top:6px; pointer-events:none; opacity:0; transition:opacity .1s; background:var(--surface); border:1px solid var(--line); border-radius:8px; box-shadow:var(--shadow-pop); padding:5px 9px; font-size:15px; white-space:nowrap; z-index:2; }
.kc-tip b{ font-variant-numeric:tabular-nums; font-weight:700; }
.kc-tip .kc-tip-x{ font-family:var(--mono); font-size:13px; letter-spacing:var(--track-caps); text-transform:uppercase; color:var(--muted); margin-right:8px; }
/* Cadence card: trace + distribution side by side, stacking on narrow widths */
.cad-wrap{ display:flex; gap:20px; align-items:stretch; margin-top:10px; }
.cad-trace{ flex:1 1 60%; min-width:0; position:relative; }
.cad-tip{ position:absolute; top:6px; pointer-events:none; opacity:0; transition:opacity .1s; background:var(--surface); border:1px solid var(--line); border-radius:8px; box-shadow:var(--shadow-pop); padding:5px 9px; font-size:15px; white-space:nowrap; z-index:2; }
.cad-tip b{ font-variant-numeric:tabular-nums; font-weight:700; }
.cad-tip .cad-tip-x{ font-family:var(--mono); font-size:13px; letter-spacing:var(--track-caps); text-transform:uppercase; color:var(--muted); margin-right:8px; }
.cad-dist{ flex:1 1 34%; min-width:0; border-left:1px solid var(--line-2); padding-left:16px; }
@media (max-width:760px){ .cad-wrap{ flex-direction:column; gap:8px; } .cad-dist{ border-left:0; padding-left:0; border-top:1px solid var(--line-2); padding-top:8px; } }

/* Plans: weeks x days builder — mirrors the calendar's joined-grid look */
.pl-card{ margin-bottom:12px; }
.pl-scroll{ overflow-x:auto; }
.pl-cal{ display:grid; grid-template-columns:82px repeat(7,minmax(0,1fr)); border:1px solid var(--line); border-radius:var(--r-lg); overflow:hidden; background:var(--surface); min-width:780px; }
.pl-hrow, .pl-wrow{ display:contents; }   /* rows flatten into the grid on desktop; they become cards on mobile */
.pl-cell-dow{ display:none; }             /* per-cell day label, shown only in the mobile stacked layout */
.pl-h{ font-family:var(--mono); font-size:13px; letter-spacing:var(--track-caps); text-transform:uppercase; font-weight:600; color:var(--muted); padding:10px 12px; border-bottom:1px solid var(--line); background:var(--inset); text-align:center; }
.pl-wk{ position:relative; border-right:1px solid var(--line); border-bottom:1px solid var(--line-2); background:var(--inset); padding:9px 8px; display:flex; flex-direction:column; gap:3px; font-family:var(--mono); font-size:13px; font-weight:700; color:var(--ink-2); }
.pl-wkt{ font-size:13px; color:var(--muted); font-weight:600; }
.pl-wx{ position:absolute; top:6px; right:6px; width:24px; height:24px; display:flex; align-items:center; justify-content:center; border-radius:50%; cursor:pointer; color:var(--muted); font-size:18px; line-height:1; transition:background .12s ease, color .12s ease; }
.pl-wx:hover{ background:var(--line-2); color:var(--accent); }
.pl-cell{ position:relative; min-height:112px; border-right:1px solid var(--line-2); border-bottom:1px solid var(--line-2); padding:8px 8px; display:flex; flex-direction:column; gap:5px; cursor:pointer; transition:background .14s ease; }
.pl-cell:hover{ background:var(--inset); }
.pl-cell .wo{ cursor:pointer; }
.pl-add{ margin:auto; color:var(--faint); font-size:22px; font-weight:400; opacity:.4; transition:opacity .12s ease; }
.pl-cell:hover .pl-add{ opacity:1; }
.pl-rest{ margin:auto; color:var(--faint); font-size:13px; font-weight:600; }
.pl-cx{ position:absolute; top:4px; right:5px; width:24px; height:24px; display:flex; align-items:center; justify-content:center; border-radius:50%; color:var(--muted); cursor:pointer; font-size:18px; line-height:1; z-index:2; transition:background .12s ease, color .12s ease; }
.pl-cx:hover{ background:var(--line-2); color:var(--accent); }
/* Plans: workout-library picker popup */
.pl-modal-back{ position:fixed; inset:0; background:rgba(20,24,32,.45); display:flex; z-index:110; padding:24px; overflow:auto; }
.pl-modal{ background:var(--surface); border:1px solid var(--line); border-radius:16px; box-shadow:var(--shadow-pop); width:min(1000px,96vw); max-height:88vh; overflow:auto; margin:auto; padding:24px; }
.pl-modal-head{ display:flex; align-items:center; gap:10px; margin-bottom:16px; }
.pl-pickgrid{ display:grid; grid-template-columns:repeat(auto-fill,minmax(220px,1fr)); gap:12px; }
.pl-pick{ text-align:left; cursor:pointer; background:var(--surface); border:1px solid var(--line); border-radius:12px; padding:14px; display:flex; flex-direction:column; gap:8px; transition:border-color .12s ease, box-shadow .12s ease, transform .12s ease; font:inherit; }
.pl-pick:hover{ border-color:var(--muted); box-shadow:var(--shadow); transform:translateY(-1px); }
.pl-pick-top{ display:flex; align-items:center; gap:8px; }
.pl-pick-m{ font-size:13px; color:var(--muted); font-variant-numeric:tabular-nums; }
.pl-pick-name{ font-weight:700; font-size:15px; color:var(--ink); line-height:1.3; }
/* nav "New" badge */
.nav-new{ margin-left:auto; font-family:var(--mono); font-size:13px; font-weight:700; letter-spacing:.02em; color:#fff; background:var(--accent); border-radius:999px; padding:1px 7px; }
/* editable plan name — reads as a rename field, not static text */
.pl-name{ position:relative; flex:1; min-width:180px; display:flex; align-items:center; gap:8px; border-bottom:1.5px solid var(--line); transition:border-color .12s ease; }
.pl-name:hover, .pl-name:focus-within{ border-bottom-color:var(--ink); }
.pl-name-in{ flex:1; min-width:0; font-family:inherit; font-size:22px; font-weight:700; color:var(--ink); border:0; background:transparent; padding:4px 0; }
.pl-name-in:focus{ outline:none; }
.pl-name-ic{ flex:none; color:var(--faint); transition:color .12s ease; }
.pl-name:hover .pl-name-ic, .pl-name:focus-within .pl-name-ic{ color:var(--ink); }
/* mobile: the weeks x days grid stacks into per-week cards, days as rows */
@media (max-width:760px){
  .pl-scroll{ overflow-x:visible; }
  .pl-cal{ display:block; min-width:0; border:0; border-radius:0; background:transparent; }
  .pl-hrow{ display:none; }
  .pl-wrow{ display:block; border:1px solid var(--line); border-radius:var(--r-lg); overflow:hidden; margin-bottom:14px; background:var(--surface); }
  .pl-wk{ flex-direction:row; align-items:center; border-right:0; padding:11px 14px; }
  .pl-wkt{ margin-left:8px; }
  .pl-wx{ position:static; margin-left:auto; }
  .pl-cell{ min-height:0; border-right:0; flex-direction:row; align-items:center; gap:12px; padding:10px 14px; }
  .pl-cell:last-child{ border-bottom:0; }
  .pl-cell-dow{ display:block; font-family:var(--mono); font-size:13px; text-transform:uppercase; letter-spacing:var(--track-caps); color:var(--muted); font-weight:700; width:34px; flex:none; }
  .pl-cell .wo{ flex:1; }
  .pl-add{ margin:0; opacity:.55; font-size:18px; }
  .pl-rest{ margin:0; flex:1; text-align:left; }
  .pl-cx{ position:static; margin-left:auto; }
  .pl-card>div{ flex-wrap:wrap; }
}

/* ================= mobile ================= */
.mobnav{ display:none; }
.mobnav-btn{ flex:1; min-width:0; border:0; background:transparent; color:var(--faint); display:grid; place-items:center; height:100%; cursor:pointer; padding:0; }
.mobnav-btn svg{ width:22px; height:22px; }
.mobnav-btn.active{ color:var(--ink); }
.mobnav-btn.active svg{ stroke:var(--accent); }
.w-grip{ touch-action:none; }

@media (max-width:760px){
  .app{ grid-template-columns:1fr; }
  /* Only a widget, table, or chart may scroll sideways - never the whole page.
     Clamp the page containers to the viewport so a stray-wide child can't push
     the whole screen off (which is what forced the pinch-to-zoom). Wide content
     provides its own inner scroll. No sticky element is active on mobile (the
     rail is hidden), so hiding the body's x-overflow is safe here. */
  html, body{ overflow-x:hidden; max-width:100%; }
  .app, .main, .screen, .grid, .w-grid{ min-width:0; max-width:100%; }
  .rail{ display:none; }
  .mobnav{ display:flex; position:fixed; left:0; right:0; bottom:0; height:58px; background:var(--surface); border-top:1px solid var(--line); z-index:60; padding:0 2px; box-shadow:0 -2px 14px rgba(0,0,0,.06); }
  .main{ padding-bottom:66px; }
  .screen{ padding:14px 14px 26px; }
  .screen h1{ font-size:22px !important; line-height:1.15; }
  .topbar{ flex-wrap:wrap; gap:10px; }
  .topbar-right{ width:100%; margin-left:0; gap:8px; justify-content:flex-start; }
  .topbar-right .btn{ font-size:13px; padding:8px 11px; white-space:nowrap; }
  .topbar-right .btn svg{ width:13px; height:13px; }
  .grid, .w-grid{ grid-template-columns:1fr !important; gap:12px; }
  .col-3,.col-4,.col-5,.col-6,.col-7,.col-8,.col-9,.col-10,.col-12,.widget{ grid-column:1 / -1 !important; }
  .ad-stats{ grid-template-columns:repeat(2,1fr) !important; }
  .cg{ grid-template-columns:repeat(2,1fr) !important; }
  .cg .cg-cell:nth-child(-n+2){ border-top:0; }
  .ad-dl{ grid-template-columns:1fr !important; }
  .ad-an-tiles{ grid-template-columns:repeat(2,1fr) !important; }
  .ad-hero-item{ min-width:42% !important; padding:2px 14px; }
  .card:has(table.tbl){ overflow-x:auto; -webkit-overflow-scrolling:touch; }
  table.tbl{ min-width:460px; }
  .w-grid.editing .widget{ touch-action:none; }
  .cg.editing .cg-cell{ touch-action:none; }
  .w-toolbar{ flex-wrap:wrap; }
  .ad-chart-head{ gap:8px; }
  .ad-tools{ flex-wrap:wrap; }
}

/* session completion modal (RPE / feel / notes) */
.cf-lab{ font-family:var(--mono); font-size:13px; letter-spacing:var(--track-caps); text-transform:uppercase; color:var(--muted); font-weight:600; margin-bottom:9px; }
.rpe-row{ display:grid; grid-template-columns:repeat(10,1fr); gap:6px; }
.rpe-b{ border:1px solid var(--line); background:var(--surface); color:var(--ink-2); border-radius:var(--r-md); padding:10px 0; font-weight:700; font-size:15px; cursor:pointer; font-family:var(--mono); transition:.12s; }
.rpe-b:hover{ border-color:var(--muted); }
.rpe-b.on{ background:var(--ink); color:#fff; border-color:var(--ink); }
.feel-row{ display:flex; gap:8px; flex-wrap:wrap; }
.feel-b{ display:inline-flex; align-items:center; gap:8px; border:1px solid var(--line); background:var(--surface); color:var(--ink-2); border-radius:var(--r-xl); padding:8px 16px; font-weight:600; font-size:15px; cursor:pointer; transition:.12s; }
.feel-dot{ width:9px; height:9px; border-radius:50%; background:var(--fc,var(--muted)); flex:none; }
.feel-b:hover{ border-color:var(--muted); }
/* Selected: adopt the feel's own colour (outline + text), legible on white for every
   step of the ramp - a filled swatch would leave yellow/amber text unreadable. */
.feel-b.on{ color:var(--fc); border-color:var(--fc); box-shadow:inset 0 0 0 1px var(--fc); background:var(--surface); }
.cf-notes{ width:100%; border:1px solid var(--line); border-radius:var(--r-md); padding:11px 12px; font-family:var(--sans); font-size:15px; line-height:1.5; background:var(--surface); color:var(--ink); resize:vertical; }
.cf-notes:focus{ outline:none; border-color:var(--accent); }
@media (max-width:520px){ .rpe-row{ grid-template-columns:repeat(5,1fr); } }

/* ===== share-to-socials card (offered after a fresh session is saved) ===== */
.sh-back{ position:fixed; inset:0; background:rgba(20,24,32,.55); display:grid; place-items:center; z-index:120; padding:20px; overflow:auto; }
.sh-modal{ background:var(--surface); border:1px solid var(--line); border-radius:var(--r-xl); box-shadow:var(--shadow-pop); width:min(440px,100%); padding:22px; }
.sh-head{ display:flex; align-items:center; margin-bottom:16px; }
.sh-head h2{ margin:0; font-size:22px; font-weight:700; }
.sh-head h2::first-letter{ text-transform:uppercase; }
.sh-head .sh-x{ margin-left:auto; width:34px; height:34px; padding:0; justify-content:center; font-size:22px; line-height:1; }
.sh-canvas-wrap{ border-radius:var(--r-xl); overflow:hidden; background:var(--inset); display:grid; place-items:center; aspect-ratio:1/1; }
.sh-canvas{ display:block; width:100%; height:auto; }
.sh-loading{ color:var(--muted); font-size:15px; }
.sh-actions{ display:flex; gap:10px; margin-top:18px; }
.sh-actions .btn{ flex:1; justify-content:center; }

/* upload dropdown menu */
.up-menu{ position:fixed; z-index:130; background:var(--surface); border:1px solid var(--line); border-radius:var(--r-lg); box-shadow:var(--shadow-pop); padding:6px; min-width:230px; }
.up-item{ display:flex; gap:11px; align-items:flex-start; padding:10px 11px; border-radius:var(--r-md); cursor:pointer; }
.up-item:hover{ background:var(--inset); }
.up-item .ui-ic{ width:30px; height:30px; border-radius:var(--r-sm); background:var(--inset); border:1px solid var(--line); display:grid; place-items:center; flex:none; color:var(--ink-2); }
.up-item .ui-ic svg{ width:17px; height:17px; }
.up-item .ui-t{ font-weight:600; font-size:15px; color:var(--ink); }
.up-item .ui-d{ font-size:15px; color:var(--muted); margin-top:1px; line-height:1.4; }

/* ===== Health & recovery dashboard ===== */
.h-toggle{ display:inline-flex; gap:2px; background:var(--inset); border:1px solid var(--line); border-radius:var(--r-sm); padding:2px; }
.h-tg{ font:600 13px/1 var(--sans); letter-spacing:.02em; color:var(--muted); background:transparent; border:0; padding:7px 11px; border-radius:var(--r-sm); cursor:pointer; }
.h-tg:hover{ color:var(--ink); }
.h-tg.on{ background:var(--surface); color:var(--ink); box-shadow:0 1px 2px rgba(0,0,0,.06); }
.h-tg .h-sw{ width:9px; height:9px; border-radius:50%; border:1.5px solid; display:inline-block; margin-right:6px; vertical-align:middle; }
.h-zoom{ display:flex; align-items:center; gap:12px; margin:4px 2px 0; min-height:24px; }
.h-reset{ font:600 13px/1 var(--sans); color:var(--ink); background:var(--inset); border:1px solid var(--line); border-radius:var(--r-sm); padding:5px 10px; cursor:pointer; }
.h-reset:hover{ border-color:var(--muted); }
.h-legend{ display:flex; flex-wrap:wrap; gap:14px; margin:6px 2px 4px; font-size:15px; color:var(--muted); }
.h-legend span{ display:inline-flex; align-items:center; gap:6px; }
.h-legend i{ width:10px; height:10px; border-radius:50%; display:inline-block; }
.h-legend i.h-bar{ width:4px; height:12px; border-radius:1px; background:var(--line); }
.h-split{ display:grid; grid-template-columns:1fr 1fr; gap:18px; margin-top:14px; }
.h-day{ background:var(--inset); border:1px solid var(--line); border-radius:var(--r-md); padding:14px 16px; }
.h-day-h{ margin-bottom:8px; }
/* Day readout: name over its normal on the left, today's reading over the
   verdict on it at the right. Both columns keep a hard edge at every width. */
.h-drow{ display:grid; grid-template-columns:1fr auto; column-gap:14px; row-gap:2px;
  align-items:baseline; padding:9px 0; border-bottom:1px solid var(--line); }
.h-drow:last-of-type{ border-bottom:0; }
.h-dk{ color:var(--muted); font-size:15px; white-space:nowrap; }
.h-dv{ font-variant-numeric:tabular-nums; text-align:right; white-space:nowrap; }
.h-dv b{ font-size:18px; font-weight:800; }
.h-dv small{ color:var(--muted); font-weight:600; font-size:13px; }
.h-dref{ color:var(--muted); font-weight:600; font-size:13px; white-space:nowrap; }
.h-dstate{ font-size:13px; font-weight:600; text-transform:uppercase; letter-spacing:var(--track-caps);
  text-align:right; white-space:nowrap; }
.h-resp{ display:flex; flex-direction:column; }
.h-rgrid{ display:flex; justify-content:space-between; margin-bottom:2px; }
.h-raxis{ flex:1; font-size:13px; color:var(--faint); text-transform:uppercase; font-weight:600; letter-spacing:var(--track-caps); }
.h-rrow{ display:flex; align-items:center; gap:10px; padding:5px 0; }
.h-rcat{ width:96px; font-size:15px; color:var(--ink); flex:none; }
.h-rtrack{ position:relative; flex:1; height:8px; background:var(--inset); border-radius:var(--r-sm); }
.h-rtrack:before{ content:""; position:absolute; left:50%; top:-2px; bottom:-2px; width:1px; background:var(--line); }
.h-rz{ position:absolute; top:0; height:100%; border-radius:var(--r-sm); }
.h-rn{ width:68px; text-align:right; font:600 13px/1 var(--mono); color:var(--muted); white-space:nowrap; }
@media(max-width:720px){ .h-split{ grid-template-columns:1fr; } }
.h-diag{ width:100%; border-collapse:collapse; margin-top:8px; font:600 13px/1.4 var(--mono); }
.h-diag th,.h-diag td{ text-align:left; padding:6px 10px; border-bottom:1px solid var(--line); color:var(--ink); white-space:nowrap; }
.h-diag th{ color:var(--muted); text-transform:uppercase; font-weight:600; letter-spacing:var(--track-caps); font-size:13px; }

/* ===== mobile calendar agenda ===== */
.cal-ag{ display:flex; flex-direction:column; border:1px solid var(--line); border-radius:var(--r-lg); overflow:hidden; background:var(--surface); }
.ag-wk{ display:flex; justify-content:space-between; align-items:center; gap:10px; padding:9px 14px; background:var(--inset); border-top:1px solid var(--line); border-bottom:1px solid var(--line); font-size:13px; color:var(--muted); }
.ag-wk:first-child{ border-top:0; }
.ag-wk .ag-tot{ font-variant-numeric:tabular-nums; white-space:nowrap; }
.ag-wk .ag-tot b{ color:var(--ink); font-weight:700; }
.ag-day{ display:flex; gap:13px; padding:12px 14px; border-bottom:1px solid var(--line-2); align-items:flex-start; }
.ag-day:last-child{ border-bottom:0; }
.ag-day.today{ box-shadow:inset 3px 0 0 var(--ink); background:var(--inset); }
.ag-day.dim{ opacity:.55; }
.ag-d{ width:40px; flex:none; text-align:center; padding-top:2px; }
.ag-dow{ display:block; font-size:13px; text-transform:uppercase; font-weight:600; letter-spacing:var(--track-caps); color:var(--muted); }
.ag-dn{ display:block; font-size:22px; font-weight:800; line-height:1.1; font-variant-numeric:tabular-nums; }
.ag-day.today .ag-dow{ color:var(--ink); }
.ag-items{ flex:1; display:flex; flex-direction:column; gap:6px; min-width:0; }
.ag-rest{ color:var(--faint); font-size:15px; padding-top:6px; }

/* ===== workout builder stats (wrap 2-up on small screens) ===== */
.wb-stats{ display:flex; flex-wrap:wrap; gap:12px 26px; margin-bottom:12px; }
.wb-stats>div{ flex:1 1 40%; min-width:110px; }
/* On a phone the 5-button action bar can't fit one row - it used to run off the
   right edge, taking "Save to calendar" off-screen. Wrap it, drop the desktop
   spacer, and pin the primary Save action full-width at the top of the bar. */
@media(max-width:760px){
  .wb-overlay{ padding:12px !important; }
  .wb-actions{ gap:8px; }
  .wb-actions .wb-actions-sp{ display:none; }
  .wb-actions .btn{ flex:1 1 46%; justify-content:center; }
  .wb-actions .btn-primary{ flex-basis:100%; order:-1; }
}

/* ===== more mobile polish ===== */
@media(max-width:600px){
  /* health & recovery: toggles drop below the title, scroll rather than cram */
  #healthCard .card-head{ flex-wrap:wrap; row-gap:8px; }
  #healthCard .h-toggle{ width:100%; overflow-x:auto; -webkit-overflow-scrolling:touch; }
  #healthCard .h-tg{ white-space:nowrap; flex:none; }
  /* settings: stack each row (label+hint full width, control below) so short
     descriptions stop wrapping into 3 cramped lines */
  .field{ flex-direction:column; align-items:stretch; gap:8px; }
  .field input.inp, .field select.inp{ width:100%; min-width:0; text-align:left; }
  .field .toggle{ align-self:flex-start; }
  .field .btn{ white-space:nowrap; align-self:flex-start; }
  /* records tables: contain any overflow inside the card instead of the page */
  .card.pad0{ overflow-x:auto; }
  .stat-flow{ gap:18px 22px; }
  /* workout builder modal: tighter padding so nothing runs off the sheet */
  #wbPanel{ padding:18px !important; }
}

/* calendar drag-and-drop to reschedule planned workouts */
/* Calendar affordances. A session chip opens the session and a day cell accepts
   a drop, but neither said so: both were inert until you clicked. */
.wo{ transition:background .14s ease, border-color .14s ease, transform .14s ease; }
.wo:hover{ background:var(--surface); box-shadow:var(--shadow); transform:translateY(-1px); }
.wo:hover .wt{ color:var(--accent); }
.cal-cell:hover, .ag-day:hover{ background:var(--inset); }
.cal-cell, .ag-day{ transition:background .14s ease; }

.wo.wo-move{ cursor:grab; }
.wo.wo-move:active{ cursor:grabbing; }
.wo.wo-dragging{ opacity:.4; }
.cal-cell.day-drop, .ag-day.day-drop{ outline:2px dashed var(--accent); outline-offset:-2px; background:color-mix(in srgb, var(--accent) 8%, transparent); }
/* glass-box insight strip */
.ins-card .ins{ padding:11px 0; border-top:1px solid var(--line-2); }
.ins-card .ins:first-of-type{ border-top:0; padding-top:0; }
.ins-claim{ display:flex; gap:9px; align-items:flex-start; font-size:15px; line-height:1.5; color:var(--ink); font-weight:600; }
.ins-claim .ins-ic{ margin-top:2px; }
.ins-evs{ display:flex; flex-wrap:wrap; gap:7px; margin:9px 0 0 24px; }
.ins-ev{ font-size:15px; color:var(--muted); background:var(--inset); border:1px solid var(--line); border-radius:var(--r-sm); padding:3px 9px; }
.ins-act{ margin:9px 0 0 24px; font-size:15px; line-height:1.5; color:var(--ink-2); }
.ins-act .ins-act-k{ display:inline-block; font-family:var(--mono); font-size:13px; letter-spacing:var(--track-caps); text-transform:uppercase; font-weight:600; color:var(--accent); background:var(--inset); border:1px solid var(--line); border-radius:var(--r-sm); padding:1px 7px; margin-right:8px; vertical-align:1px; }
.ins-conf{ display:flex; align-items:center; gap:6px; margin:9px 0 0 24px; font-size:15px; color:var(--faint); text-transform:capitalize; }
.ins-conf .ins-dot{ width:7px; height:7px; border-radius:50%; }
.spinner{ width:34px; height:34px; border-radius:50%; border:3px solid var(--line); border-top-color:var(--accent); animation:spin .8s linear infinite; }
@keyframes spin{ to{ transform:rotate(360deg); } }
@media(prefers-reduced-motion:reduce){ .spinner{ animation-duration:2s; } }

  /* Widget load-in: a short rise + fade, staggered by position, so the dashboard
     assembles instead of appearing all at once. --w-delay is set per widget in
     renderWidgets. Runs on every navigate() render, which is what makes moving
     between views feel like the app is drawing rather than swapping. */
  @keyframes w-rise { from { opacity:0; transform:translateY(10px); } to { opacity:1; transform:none; } }
  /* fill-mode BACKWARDS, not both: backwards still hides the widget through its
     stagger delay, but releases the animation once it finishes. "both" kept the
     finished transform applied forever, which made every widget a permanent
     stacking context and a containing block for position:fixed - so the info
     tooltips painted behind whichever widget came later, no z-index able to
     save them from inside their own trap. */
  .widget.w-rise { animation:w-rise .42s cubic-bezier(.22,.68,.36,1) backwards; animation-delay:var(--w-delay,0ms); }
  /* belt and braces: if any future effect re-creates a stacking context on a
     widget, the one hosting a hovered tooltip still wins the paint order */
  .widget:has(.itip:hover){ position:relative; z-index:130; }
  @media (prefers-reduced-motion:reduce){ .widget.w-rise { animation:none; } }

  /* Whole-page load-in for the views that don't stagger their own widgets
     (everything but the dashboard): the same rise+fade as w-rise, applied to the
     screen as one block on each navigate() so moving between pages feels like the
     app is drawing, not swapping. BACKWARDS fill for the very reason widgets use
     it - #screen is the ancestor of every info tooltip, and a retained transform
     here would make it a containing block that traps their position:fixed. */
  .screen.page-in { animation:w-rise .42s cubic-bezier(.22,.68,.36,1) backwards; }
  @media (prefers-reduced-motion:reduce){ .screen.page-in { animation:none; } }

  /* Post-session snapshot: what you just did, above the RPE buttons. Auto-fit
     columns so a manually logged run (three fields) and a .fit ride with power
     (seven) both fill the row instead of leaving gaps. */
  .cf-sub { margin:8px 0 14px; color:var(--faint); font-size:15px; font-family:var(--mono);
    letter-spacing:var(--track-caps); text-transform:uppercase; }
  /* Spaced cards, not a hairline grid: a leftover slot in the last row is then just
     transparent space, never a grey empty box, whatever the field count. */
  .cf-snap { display:grid; grid-template-columns:repeat(auto-fit,minmax(150px,1fr)); gap:8px; margin-bottom:20px; }
  .cf-stat { background:var(--inset); border:1px solid var(--line); border-radius:var(--r-md); padding:12px 14px; }
  .cf-stat .k { font-size:13px; color:var(--faint); font-family:var(--mono);
    letter-spacing:var(--track-caps); text-transform:uppercase; margin-bottom:3px; }
  .cf-stat .v { font-size:18px; font-weight:700; font-variant-numeric:tabular-nums; color:var(--ink); line-height:1.2; }
  .cf-stat .s { font-size:15px; color:var(--muted); margin-top:2px; }
  /* Phone: two roomy columns so every value sits on one line; a lone last card
     spans the row instead of leaving a half-width gap. */
  @media (max-width:520px){
    .cf-snap { grid-template-columns:repeat(2,1fr); gap:8px; }
    .cf-stat { padding:13px 15px; }
    .cf-snap .cf-stat:last-child:nth-child(odd){ grid-column:1 / -1; }
  }
  /* The filter-group divider only makes sense on one row; it dangles once the
     status and sport chips wrap onto separate rows on a phone. */
  @media (max-width:520px){ .fdiv{ display:none; } }

/* ---- Climbing & VAM widget ----
   The lead row is two figures, then a VAM-against-gradient scatter. Sizes come
   from .stat/.note so nothing here reintroduces an off-scale font-size. */
.vam-lead{ display:flex; gap:34px; flex-wrap:wrap; margin:6px 0 2px; }
.vam-u{ font-size:15px; font-weight:600; color:var(--ink-2); letter-spacing:0; }
.vam-key{ display:flex; align-items:center; gap:16px; flex-wrap:wrap; margin-top:8px; }
.vam-key i.vam-dot{
  display:inline-block; width:9px; height:9px; border-radius:50%;
  background:var(--muted); opacity:.4; margin-right:6px; vertical-align:middle;
}
.vam-key i.vam-dot.on{ background:var(--bike); opacity:1; }
.vam-key .vam-hint{ color:var(--muted); margin-left:auto; }
@media(max-width:560px){ .vam-lead{ gap:22px; } }
/* VAM readout row: fixed min-height so hovering a climb does not shift the card. */
.vam-read{ min-height:34px; margin:2px 2px 0; display:flex; align-items:center; }
.vam-read-hint{ color:var(--faint); }
.vam-read-in{ display:flex; align-items:baseline; gap:10px; flex-wrap:wrap; font-size:var(--fs-body); }
.vam-read-in b{ color:var(--ink); font-weight:650; }
.vam-read-d{ color:var(--faint); }
.vam-read-s{ color:var(--muted); font-family:var(--mono); }
.vam-pt{ cursor:pointer; }
